You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React开发问题:无法修改Quiz对象的子属性(问题及答案属性)

解决React中修改嵌套对象状态时的"object is not iterable"错误

我看了你的代码,立刻发现了问题所在——你在修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 08:57:43