React+TypeScript中Object is not extensible错误问题求助
问题解决:Object is not extensible 错误处理
错误原因
从数据库获取的对象通常是不可扩展的(比如ORM框架返回的冻结对象,或是经过Object.freeze()处理),直接给这类对象添加questionAnswer/questionAnswerText新属性、或修改属性时,就会触发object is not extensible错误。此外现有代码还存在两个问题:
- 直接修改子组件的
props.data(React props是只读的) - 使用
splice修改原数组后更新状态,违背React状态不可变原则
分步解决方案
1. 初始数据预处理:生成可扩展对象
在获取数据库数据后,立即为每个问题对象创建可扩展的副本并添加默认属性,避免后续修改报错:
// 假设fetchQuestions是获取数据库数据的函数 const fetchQuestions = async () => { const dbQuestions = await api.getQuestions(); // 为每个对象创建副本并添加默认属性 const editableQuestions = dbQuestions.map(q => ({ ...q, questionAnswer: "", questionAnswerText: "" })); setQuestionAnswer(editableQuestions); };
2. 修正子组件输入处理逻辑
子组件中禁止直接修改props.data,先创建对象副本再修改,之后传递给父组件:
const insertAnswer = (value: string, name: string) => { if (props.data.question_type_id === 6) { // 创建props.data的副本,避免修改原对象 const updatedData = { ...props.data }; if (name === "radio-buttons-group") { updatedData.questionAnswer = value; } else { updatedData.questionAnswerText = value; } // 传递副本给父组件 props.sendDataToParent(updatedData, props.count); } };
3. 修正父组件状态更新逻辑
用不可变方式更新数组,避免splice修改原数组,通过解构生成新数组替换对应元素:
{questionAnswer.map((m: IQuestion, index: number) => ( <QuestionComponent totalCount={questionAnswer.length} data={m} // 直接传预处理后的对象,无需临时添加属性 count={index + 1} sendDataToParent={(d: IQuestion, count: number) => { // 生成新数组,替换对应位置的元素 const updatedQuestions = [...questionAnswer]; updatedQuestions[count - 1] = d; setQuestionAnswer(updatedQuestions); }} /> ))}
4. 完善TypeScript类型定义
更新IQuestion接口,包含新增属性,消除类型报错:
interface IQuestion { question_id: number; question_type_id: number; question: string; section_id: number; section: string; status: number; title: string; rating_scale: string; question_html: string; questionAnswer: string; // 新增属性 questionAnswerText: string; // 新增属性 }
内容的提问来源于stack exchange,提问作者Saif Farooqui
相关产品推荐
相关产品推荐

