React题目选项随机排序失效、组件重复渲染4次问题求解
React Trivia应用问题修复方案
核心问题排查
1. 组件重复渲染4次的诱因
useEffect依赖项错误传入[1],规范写法是传空数组[]实现组件挂载时仅发起一次数据请求。- 渲染阶段直接原地修改state内的数组:代码中
const answer = incorrect_answers是浅引用,后续执行splice会直接修改state存储的原数组,触发非预期重渲染。 - 若项目开启了React严格模式,开发环境会自动双重执行渲染流程做合规性校验,叠加初始空状态渲染、数据返回后的setState渲染,累计就会出现4次渲染的现象,该双重渲染行为仅在开发环境存在,生产环境不会触发。
2. 选项随机排序失效的诱因
- 函数内写了两个
return语句:第一个return直接返回题目标题后函数就会终止执行,后面渲染选项的逻辑永远不会触发。 - 没有对原state数据做副本隔离:直接在原
incorrect_answers数组上执行splice插入正确答案,每次渲染都会重复插入一次正确答案,最终数组内会存在多个重复的正确答案,打乱逻辑完全失效。 - 现有逻辑仅做单次插入,没有对全量选项做均匀随机排序,打乱效果不符合预期。
修复后代码
const [startPage,setStartPage] = React.useState(false) // 初始值设为null,方便判断加载状态 const [questionsData,setQueationsData] = React.useState(null) React.useEffect(()=>{ fetch("https://opentdb.com/api.php?amount=1&type=multiple") .then(res => res.json()) .then(data => setQueationsData(data.results[0])) },[]) // 空依赖:仅组件首次挂载时拉取数据 // 数组随机洗牌工具函数,不修改原数组 function shuffleArray(arr) { const arrCopy = [...arr] for (let i = arrCopy.length - 1; i > 0; i--) { const randomIdx = Math.floor(Math.random() * (i + 1)); [arrCopy[i], arrCopy[randomIdx]] = [arrCopy[randomIdx], arrCopy[i]] } return arrCopy } function Question(){ // 数据未返回时展示加载态,避免直接访问空值的属性报错 if (!questionsData) { return <div>题目加载中...</div> } // 合并正确、错误答案后做随机排序,全程操作副本,不修改原state数据 const allOptions = shuffleArray([ ...questionsData.incorrect_answers, questionsData.correct_answer ]) return ( <div className="question-card"> <h3>{questionsData.question}</h3> <div className="option-group"> {allOptions.map((option, index) => ( <button key={index} className="option-item">{option}</button> ))} </div> </div> ) }
额外注意事项
- 禁止在渲染流程中直接修改state存储的数组、对象,所有修改操作必须基于副本执行,避免触发不可预期的渲染bug。
- 单个组件render函数只能有一个根返回值,多节点需要包裹在同一个父元素或React Fragment中,写在前序return之后的代码永远不会执行。
- React严格模式下的开发环境双重渲染是官方设计的校验机制,不需要特意关闭,只要遵循状态不可变原则就不会产生业务异常。
内容的提问来源于stack exchange,提问作者polmayan
相关产品推荐
相关产品推荐

