React开发问题:无法修改Quiz对象的子属性(问题及答案属性)
我看了你的代码,立刻发现了问题所在——你在修改Question和Answer字段时的setQuestion调用方式完全错了,这才导致了TypeError: object is not iterable的报错。
错误原因分析
你修改Quiz基础属性的代码是正确的:
onChange={(e)=>setQuiz({...quiz, title: e.target.value})}
这里你用对象展开运算符在新对象里复制原有属性,再覆盖需要更新的字段,符合React状态不可变更新的要求。
但到了Question的输入框,你写成了这样:
onChange={(e)=>setQuestion(...question, e.target.value)}
这里的...question是试图把一个对象拆成多个参数传给setQuestion,但对象不是可迭代类型(只有数组、字符串等才是),JS引擎会尝试迭代这个对象,自然就抛出了"object is not iterable"的错误。而且你还没指定要更新的具体字段,就算不报错,状态也会被改得一团糟。
具体修正方案
我们需要针对不同的字段,正确地进行不可变更新:
1. 修正Question基础字段的onChange
针对Question的question、value、explaination字段,要像修改Quiz属性那样,创建新的Question对象:
// Question输入框 <input value={question ? question.question: ''} onChange={(e)=>setQuestion({...question, question: e.target.value})} type="text" className="form-control stuff" id="question" placeholder="Enter question name" required /> // Value输入框(注意转成数字类型) <input value={question ? question.value: ''} onChange={(e)=>setQuestion({...question, value: Number(e.target.value)})} type="number" className="form-control stuff" id="value" required /> // Explaination输入框 <input value={question ? question.explaination: ''} onChange={(e)=>setQuestion({...question, explaination: e.target.value})} type="text" className="form-control stuff" id="explaination" placeholder="Enter Correct Explaination" required />
2. 修正Answer输入框的onChange
要修改Question里的answers数组中的某个Answer的content,需要先复制数组,再修改对应位置的元素,最后更新整个Question对象:
{ question.answers ? question.answers.map((answer, index)=>( <div key={index}> <div className="form-group"> <label htmlFor={`answer-${index}`}>Answer {index + 1}</label> <input onChange={(e) => { // 复制原answers数组,避免直接修改状态 const updatedAnswers = [...question.answers]; // 复制对应位置的Answer对象,修改content updatedAnswers[index] = {...updatedAnswers[index], content: e.target.value}; // 更新整个Question对象 setQuestion({...question, answers: updatedAnswers}); }} value={answer.content} type="text" className="form-control stuff" id={`answer-${index}`} placeholder="Enter answer display words" required /> </div> </div> )) : <br/>}
3. 新增Question时的小优化
新增Question时,最好给新Question生成一个唯一的id,避免和现有Question重复:
const addQuestionButton = () => { const newQuestionId = questionList.length > 0 ? Math.max(...questionList.map(q => q.id)) + 1 : 1; setQuestion({ id: newQuestionId, question: "", value:0, explaination: "", answers : [ {content: "", correct: false}, {content: "", correct: false}, {content: "", correct: false}, {content: "", correct: false} ] }) setShow(true) };
额外提示
你的useEffect依赖数组是空的,如果props.location.state在组件挂载后才变化,组件不会重新更新。可以把props.location.state加入依赖数组:
useEffect(() => { if (props.location.state){ setQuiz(props.location.state) setQuestionList(props.location.state.questions) setExecutedSet(true) } else{ setMissingParentData(true) } console.log(quiz) }, [props.location.state])
这样修改后,你应该就能正常修改Question和Answer的字段,新增Question也不会再报错了。
内容的提问来源于stack exchange,提问作者ABpositive

