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

React中嵌套数组对象的状态更新问题求助

解决React Quiz应用中答案选中状态修改的报错问题

问题分析

你的代码报错核心原因有两点:

  1. setQuestions的回调函数未返回新状态数组,prev.forEach执行后无返回值,最终传递给setQuestions的是undefined,导致React状态更新异常。
  2. 违反React状态不可变原则:直接操作原状态对象,且map生成的新answers数组未赋值给对应问题对象,状态未被正确更新。

修复后的代码

多选模式(允许同一问题选多个答案)

function selectAnswer(id) {
  setQuestions(prevQuestions => {
    // 遍历所有问题,生成新的问题数组
    return prevQuestions.map(question => {
      // 针对当前问题的答案数组,生成新的答案数组
      const updatedAnswers = question.answers.map(answer => {
        // 匹配到目标id时,复制答案对象并切换selected状态
        return id === answer.id 
          ? {...answer, selected: !answer.selected} 
          : answer;
      });
      // 返回新的问题对象,替换原有的answers数组
      return {...question, answers: updatedAnswers};
    });
  });
}

单选模式(同一问题只能选一个答案)

如果是单选逻辑,点击答案时需要取消同问题其他答案的选中状态,可使用以下代码:

function selectAnswer(id) {
  setQuestions(prevQuestions => {
    return prevQuestions.map(question => {
      // 判断当前问题是否包含目标答案,不包含则直接返回原问题
      const targetAnswerExists = question.answers.some(ans => ans.id === id);
      if (!targetAnswerExists) return question;

      const updatedAnswers = question.answers.map(answer => {
        return id === answer.id 
          ? {...answer, selected: true} 
          : {...answer, selected: false};
      });
      return {...question, answers: updatedAnswers};
    });
  });
}

关键修复点说明

  • 用map替代forEach:map会返回新数组,符合React状态更新需返回新引用的要求,而forEach无返回值。
  • 深度复制状态对象:通过展开运算符{...obj}创建对象副本,避免直接修改原状态,确保React能检测到状态变化并触发重渲染。
  • 正确传递新状态:回调函数必须返回最终的新状态数组,让setQuestions能正确完成状态更新。

内容的提问来源于stack exchange,提问作者pascal-prfst

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 06:40:22