Javascript 不需要的反应组件重新启动?
因此,这是一个表单,用户可以在其中添加部分以添加问题(构建测验),我注意到,当我填写Javascript 不需要的反应组件重新启动?,javascript,reactjs,states,Javascript,Reactjs,States,因此,这是一个表单,用户可以在其中添加部分以添加问题(构建测验),我注意到,当我填写答案选项并将文件放入我的dropZone(drop可以工作,但不能正确更新,您可以忽略此项)Answer选项和dropZonererender以及诸如refresh和refresh之类的字段将变为空 我不完全清楚为什么会发生这种情况,我曾尝试研究过类似的问题,但我无法让它发挥作用 我想它可能是我的Questions组件中的addQuestion函数。下面是代码: addQuestion = question
答案选项
并将文件放入我的dropZone
(drop可以工作,但不能正确更新,您可以忽略此项)Answer选项
和dropZone
rerender以及诸如refresh和refresh之类的字段将变为空
我不完全清楚为什么会发生这种情况,我曾尝试研究过类似的问题,但我无法让它发挥作用
我想它可能是我的Questions
组件中的addQuestion
函数。下面是代码:
addQuestion = question => {
questionIdx++;
var newQuestion = { uniqueId: uuid(), question: "" }
this.setState(prevState => ({
questions: [...prevState.questions, newQuestion]
}));
return { questions: newQuestion }
};
我对React和Js是新手,所以任何提示/解释都会帮上大忙。谢谢 添加新问题并更新组件状态变量
Questions
Questions(数组类型)时,整个组件(Questions
及其子组件)将经历一个更新过程,在此过程中,它将重新计算输出DOM树(虚拟DOM)基于新状态,并将其与状态更改前的虚拟DOM进行比较。在“重新发布”任何内容之前,它会检查两个版本的虚拟DOM是否与其他内容不同,如果是,它会尽可能高效地重新发布更改的部分
在您的例子中,重新计算会在许多问题
中看到许多答案
组件,并且由于答案
没有任何道具,因此它基本上是一个新的初始状态渲染,包括4个空输入。我能想到的最简单的解决方案是在Questions
组件的状态下,确保this.state.Questions
数组中的每个对象都有一个answers
属性(对象数组的类型)。在addQuestion
方法中修改var newQuestion={uniqueId:uuid(),问题:'}
将此数据包含在与该问题相关的答案中
然后,在呈现每个问题时,将此答案数据(答案数组)作为道具传递给答案
,然后根据索引(对象或字符串)依次传递给每个答案
组件。同时,必须将updateAnswers
方法作为问题
的道具传递给答案
和答案
,当答案
的输入字段更改时调用该方法。需要将问题id和答案id传递给此方法,以最终修改现在应存储在问题
组件状态中的答案数据。我调整了下面沙箱中的代码,使其符合以下要求,尽管我没有确保清除所有损坏:
import React, { Component } from "react";
import "./App.css";
var uuid = require("uuid-v4");
// Generate a new UUID
var myUUID = uuid();
// Validate a UUID as proper V4 format
uuid.isUUID(myUUID); // true
class DropZone extends Component {
constructor(props) {
super(props);
this.state = {
file: "",
fileId: uuid(),
className: "dropZone"
};
this.handleChange = this.handleChange.bind(this);
this._onDragEnter = this._onDragEnter.bind(this);
this._onDragLeave = this._onDragLeave.bind(this);
this._onDragOver = this._onDragOver.bind(this);
this._onDrop = this._onDrop.bind(this);
}
handleChange(file = "") {
this.setState({
file: URL.createObjectURL(file)
});
//document.getElementsByClassName("dropZone").style.backgroundImage = 'url(' + this.state.file + ')';
}
componentDidMount() {
window.addEventListener("mouseup", this._onDragLeave);
window.addEventListener("dragenter", this._onDragEnter);
window.addEventListener("dragover", this._onDragOver);
document
.getElementById("dragbox")
.addEventListener("dragleave", this._onDragLeave);
window.addEventListener("drop", this._onDrop);
}
componentWillUnmount() {
window.removeEventListener("mouseup", this._onDragLeave);
window.removeEventListener("dragenter", this._onDragEnter);
window.addEventListener("dragover", this._onDragOver);
document
.getElementById("dragbox")
.removeEventListener("dragleave", this._onDragLeave);
window.removeEventListener("drop", this._onDrop);
}
_onDragEnter(e) {
e.stopPropagation();
e.preventDefault();
return false;
}
_onDragOver(e) {
e.preventDefault();
e.stopPropagation();
return false;
}
_onDragLeave(e) {
e.stopPropagation();
e.preventDefault();
return false;
}
_onDrop(e, event) {
e.preventDefault();
this.handleChange(e.dataTransfer.files[0]);
let files = e.dataTransfer.files;
console.log("Files dropped: ", files);
// Upload files
console.log(this.state.file);
return false;
}
render() {
const uniqueId = this.state.fileId;
return (
<div>
<input
type="file"
id={uniqueId}
name={uniqueId}
class="inputFile"
onChange={e => this.handleChange(e.target.files[0])}
/>
<label htmlFor={uniqueId} value={this.state.file}>
{this.props.children}
<div className="dropZone" id="dragbox" onChange={this.handleChange}>
Drop or Choose File
<img src={this.state.file} id="pic" name="file" accept="image/*" />
</div>
</label>
<div />
</div>
);
}
}
class Answers extends Component {
constructor(props) {
super(props);
this.state = {
answers: props.answers,
};
this.handleUpdate = this.handleUpdate.bind(this);
}
// let event = {
// index: 1,
// value: 'hello'
// };
handleUpdate(event) {
//if ("1" == 1) // true
//if ("1" === 1) //false
// var answers = this.state.answers;
// answers[event.index] = event.value;
// this.setState(() => ({
// answers: answers
// }));
var answers = this.state.answers.slice();
for (var i = 0; i < answers.length; i++) {
if (answers[i].answerId == event.answerId) {
answers[i].answer = event.value;
break;
}
}
this.setState(() => ({
answers: answers
}));
this.props.updateAnswers(answers)
console.log(event);
}
render() {
return (
<div id="answers">
Answer Choices<br />
{this.state.answers.map((value, index) => (
<Answer
key={`${value}-${index}`}
onUpdate={this.handleUpdate}
value={value}
number={index}
name="answer"
/>
))}
</div>
);
}
}
class Answer extends Component {
constructor(props) {
super(props);
this.state = {
answer: props.value.answer,
answerId: props.value.answerId,
isCorrect: props.value.isCorrect,
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
this.setState({
answer: value
});
this.props.onUpdate({
answerId: this.state.answerId,
value
});
// let sample = {
// kyle: "toast",
// cam: "pine"
// };
// sample.kyle
// sample.cam
}
render() {
return (
<div>
<input type="checkbox" />
<input
type="text"
value={this.state.answer}
onChange={this.handleChange}
key={this.state.answerId}
name="answer"
/>
{/*console.log(this.state.answerId)*/}
</div>
);
}
}
var questionIdx = 0;
class Questions extends Component {
constructor(props) {
super(props);
this.state = {
questions: []
};
this.handleUpdate = this.handleUpdate.bind(this);
this.handleUpdate = this.handleUpdate.bind(this);
this.removeQuestion = this.removeQuestion.bind(this);
}
handleUpdate(event) {
//if ("1" == 1) // true
//if ("1" === 1) //false
var questions = this.state.questions.slice();
for (var i = 0; i < questions.length; i++) {
if (questions[i].uniqueId == event.uniqueId) {
questions[i].question = event.value;
break;
}
}
this.setState(() => ({
questions: questions
}));
console.log(event, questions);
}
updateAnswers(answers, uniqueId) {
const questions = this.state.questions
questions.forEach((question) => {
if (question.uniqueId === uniqueId) {
question.answers = answers
}
})
this.setState({
questions,
})
}
addQuestion = question => {
questionIdx++;
var newQuestion = {
uniqueId: uuid(),
question: "",
answers: [
{ answer: "", answerId: uuid(), isCorrect: false,},
{ answer: "", answerId: uuid(), isCorrect: false,},
{ answer: "", answerId: uuid(), isCorrect: false,},
{ answer: "", answerId: uuid(), isCorrect: false,}]
}
this.setState(prevState => ({
questions: [...prevState.questions, newQuestion]
}));
return { questions: newQuestion };
};
removeQuestion(uniqueId, questions) {
this.setState(({ questions }) => {
var questionRemoved = this.state.questions.filter(
props => props.uniqueId !== uniqueId
);
return { questions: questionRemoved };
});
console.log(
"remove button",
uniqueId,
JSON.stringify(this.state.questions, null, " ")
);
}
render() {
return (
<div id="questions">
<ol id="quesitonsList">
{this.state.questions.map((value, index) => (
<li key={value.uniqueId}>
{
<RemoveQuestionButton
onClick={this.removeQuestion}
value={value.uniqueId}
/>
}
{
<Question
onUpdate={this.handleUpdate}
value={value}
number={index}
updateAnswers={(answers) => this.updateAnswers(answers, value.uniqueId) }
/>
}
{<br />}
</li>
))}
</ol>
<AddQuestionButton onClick={this.addQuestion} />
</div>
);
}
}
class Question extends Component {
constructor(props) {
super(props);
this.state = {
question: props.value.question,
uniqueId: props.value.uniqueId,
answers: props.value.answers,
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
this.setState({
question: value
});
this.props.onUpdate({
uniqueId: this.state.uniqueId,
value
});
}
render() {
return (
<div id={"questionDiv" + questionIdx} key={myUUID + questionIdx + 1}>
Question<br />
<input
type="text"
value={this.state.question}
onChange={this.handleChange}
key={this.state.uniqueId}
name="question"
/>
<DropZone />
<Answers updateAnswers={this.props.updateAnswers} answers={this.state.answers} />
</div>
);
}
}
class IntroFields extends Component {
constructor(props) {
super(props);
this.state = {
title: "",
author: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
console.log([name]);
this.setState((previousState, props) => ({
[name]: value
}));
}
render() {
return (
<div id="IntroFields">
Title:{" "}
<input
type="text"
value={this.state.title}
onChange={this.handleChange}
name="title"
/>
Author:{" "}
<input
type="text"
value={this.state.author}
onChange={this.handleChange}
name="author"
/>
</div>
);
}
}
class AddQuestionButton extends Component {
addQuestion = () => {
this.props.onClick();
};
render() {
return (
<div id="addQuestionButtonDiv">
<button id="button" onClick={this.addQuestion} />
<label id="addQuestionButton" onClick={this.addQuestion}>
Add Question
</label>
</div>
);
}
}
class RemoveQuestionButton extends Component {
removeQuestion = () => {
this.props.onClick(this.props.value);
};
render() {
return (
<div id="removeQuestionButtonDiv">
<button id="button" onClick={this.removeQuestion} key={uuid()} />
<label
id="removeQuestionButton"
onClick={this.removeQuestion}
key={uuid()}
>
Remove Question
</label>
</div>
);
}
}
class BuilderForm extends Component {
render() {
return (
<div id="formDiv">
<IntroFields />
<Questions />
</div>
);
}
}
export default BuilderForm;
import React,{Component}来自“React”;
导入“/App.css”;
var uuid=require(“uuid-v4”);
//生成新的UUID
var myUUID=uuid();
//验证UUID是否为正确的V4格式
uuid.isUUID(myUUID);//真的
类DropZone扩展组件{
建造师(道具){
超级(道具);
此.state={
文件:“”,
fileId:uuid(),
类名:“dropZone”
};
this.handleChange=this.handleChange.bind(this);
this.\u onDragEnter=this.\u onDragEnter.bind(this);
这个;
this.\u onDragOver=this.\u onDragOver.bind(this);
this._onDrop=this._onDrop.bind(this);
}
handleChange(文件=“”){
这是我的国家({
文件:URL.createObjectURL(文件)
});
//document.getElementsByClassName(“dropZone”).style.backgroundImage='url('+this.state.file+');
}
componentDidMount(){
window.addEventListener(“mouseup”,this.\u ondragleef);
window.addEventListener(“dragenter”,本文件);
window.addEventListener(“dragover”,this.\u onDragOver);
文件
.getElementById(“dragbox”)
.addEventListener(“dragleave”,本文件);
window.addEventListener(“drop”,this.\u onDrop);
}
组件将卸载(){
window.removeEventListener(“mouseup”,this.\u ondragleef);
window.removeEventListener(“dragenter”,this.\u onDragEnter);
window.addEventListener(“dragover”,this.\u onDragOver);
文件
.getElementById(“dragbox”)
.removeEventListener(“dragleave”,本._ondragleef);
window.removeEventListener(“drop”,this.\u onDrop);
}
_昂德拉金特(e){
e、 停止传播();
e、 预防默认值();
返回false;
}
_昂德拉戈弗(e){
e、 预防默认值();
e、 停止传播();
返回false;
}
_昂德拉格(e){
e、 停止传播();
e、 预防默认值();
返回false;
}
_昂德罗普(e,事件){
e、 预防默认值();
this.handleChange(e.dataTransfer.files[0]);
让files=e.dataTransfer.files;
log(“已删除的文件:”,文件);
//上传文件
log(this.state.file);
返回false;
}
render(){
const uniqueId=this.state.fileId;
返回(
this.handleChange(e.target.files[0])]
/>
{this.props.children}
删除或选择文件
);
}
}
类扩展组件{
建造师(道具){
超级(道具);
此.state={
答案:道具,答案,
};
this.handleUpdate=this.handleUpdate.bind(this);
}
//让事件={
//索引:1,
//值:“你好”
// };
handleUpdate(事件){
//如果(“1”==1)//true
//如果(“1”==1)//false
//var answers=this.state.answers;
//答案[event.index]=event.value;
//此.setState(()=>({
//答案:答案
// }));
var answers=this.state.answers.slice();
对于(变量i=0;i({
答案:答案
}));
此.props.updateAnswers(答案)
console.log(事件);
}
伦德