如何映射题目类对象?遇answerOptions未定义及DND拖拽splice问题
报错根因
- 初始数据源存在语法错误:原结构中第二个选项的
result字段值为未定义的correctAnswer引用,JS执行初始化时就会直接抛出ReferenceError,导致后续访问路径断裂。 - 变量名大小写不匹配:代码中访问的是大写开头的
Questions,但定义的初始数组为小写的questions,JS严格区分大小写时就会直接获取到undefined,自然读不到后续的answerOptions属性。 - 拖拽splice操作层级错误:更新数组时没有按题目对象 -> answerOptions的层级做不可变更新,要么直接覆盖了当前题目对象、要么currentQuestion索引越界,最终导致取到的题目对象上没有
answerOptions字段。
修复方案
1. 修正初始数据源的语法问题
删除未定义的correctAnswer引用,给每个选项的result字段设置统一的空初始值:
const questions = [ { id:1, questionText: 'W którym roku firma apple wprowadziła do sprzedaży pierwszy komputer?', answerOptions: [ { id: 1, answerText: 'A.1974', isCorrect: false, result: [] }, { id: 2, answerText: 'B.1976', isCorrect: true, result: [] }, { id: 3, answerText: 'C.1984', isCorrect: false, result: [] }, { id: 4, answerText: 'D.1990', isCorrect: false, result: [] }, ], } ]
2. 修正映射逻辑的取值路径
匹配正确的变量名,加上*可选链?.*做兜底,避免索引越界、对象不存在时直接抛出属性访问错误:
// 注意变量名和定义的questions保持一致,全部小写 questions?.[currentQuestion]?.answerOptions?.map( ({ id, answerText, isCorrect, result }, index) => { return ( <Draggable key={`draggable2-${id}`} draggableId={`draggable2-${id}`} index={index} > {(provided, snapshot) => { return ( <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} > <div className="answer" onClick={() => handleAnswerClick(isCorrect)} > <div className="answerText">{answerText}</div> <div className={resultCorrect}>{result}</div> </div> </div> ); }} </Draggable> ); } )
3. 修正拖拽排序的splice操作逻辑
不要直接在原state上做原地修改,严格按照「复制题目对象->复制answerOptions数组->执行splice排序->把排序结果挂回题目对象->回写整个state数组」的层级更新,避免弄丢answerOptions字段:
const onDragEnd = (result) => { const { source, destination } = result; // 无有效落点时直接返回,不执行操作 if (!destination) return; setQuestions(prev => { // 先拿到当前题目的浅拷贝,避免直接修改原对象 const copiedCurrentQuestion = {...prev[currentQuestion]}; // 拷贝answerOptions数组,不直接在原数组上splice const copiedAnswerList = Array.from(copiedCurrentQuestion.answerOptions); // 执行元素移动 const [movedItem] = copiedAnswerList.splice(source.index, 1); copiedAnswerList.splice(destination.index, 0, movedItem); // 把排序后的列表挂回拷贝的题目对象 copiedCurrentQuestion.answerOptions = copiedAnswerList; // 把更新后的题目放回外层数组,生成新的state const newQuestionList = Array.from(prev); newQuestionList[currentQuestion] = copiedCurrentQuestion; return newQuestionList; }) }
内容的提问来源于stack exchange,提问作者FAFLUN
相关产品推荐
相关产品推荐

