React中如何实现数组元素单次随机排序(可使用useEffect)
问题根因分析
- 你当前的写法核心问题是:打乱后的答案没有持久化存储,每次组件重渲染都会重新生成原始顺序的答案数组
- 你写的useEffect完全不生效:useEffect执行时机在组件渲染完成之后,此时你修改的
allAnswers只是当前渲染周期的临时局部变量,既不会触发重新渲染,下一次组件重渲染时又会重新生成未打乱的、正确答案在末尾的allAnswers数组 - 如果直接删掉useEffect把shuffle写在顶层,每次点击按钮触发组件状态更新、组件重渲染时都会重新执行shuffle,自然就会出现点击后答案顺序错乱的问题
修复方案
核心逻辑:用useState存储打乱后的答案数组,仅在当前题目(props.result)变化时才重新生成并打乱,同个题目下无论多少次重渲染都用同一套顺序的答案。
具体实现代码
import { useState, useEffect, useMemo } from 'react' import { nanoid } from 'nanoid' // 可直接使用你自己实现的shuffle函数 function shuffle(array) { return [...array].sort(() => Math.random() - 0.5) } function Question(props) { const correctId = useMemo(() => nanoid(), [props.result.correct_answer]) const incorrectIds = useMemo(() => [nanoid(), nanoid(), nanoid()], [props.result.incorrect_answers]) // 用state存打乱后的答案列表,仅当题目数据变化时才重新生成 const [shuffledAnswers, setShuffledAnswers] = useState([]) useEffect(() => { // 先整理所有答案的纯数据,不直接存JSX方便后续处理 const rawAnswers = [ ...props.result.incorrect_answers.map((answer, index) => ({ text: answer, type: 'incorrect', id: incorrectIds[index] })), { text: props.result.correct_answer, type: 'correct', id: correctId } ] // 打乱后存入state setShuffledAnswers(shuffle(rawAnswers)) }, [props.result, correctId, incorrectIds]) // 依赖仅为题目相关数据,只有换题才会重新执行打乱 // 抽离公共的按钮渲染逻辑 const renderAnswerButton = (answer) => { return ( <button value={answer.type} id={answer.id} onClick={e => { changeClass(correctId, 'correct') if (answer.type === 'incorrect') { changeClass(answer.id, 'incorrect') } props.answerQuestion(e, answer.type) }} > {answer.text} </button> ) } return ( <div className="question"> <h3>{props.result.question}</h3> <div className="answers"> {shuffledAnswers.map(answer => renderAnswerButton(answer))} </div> </div> ) }
更简洁的替代写法
如果你不想额外声明state和useEffect,也可以直接用useMemo实现,效果完全一致:
const shuffledAnswers = useMemo(() => { const rawAnswers = [ ...props.result.incorrect_answers.map((answer, index) => ({ text: answer, type: 'incorrect', id: incorrectIds[index] })), { text: props.result.correct_answer, type: 'correct', id: correctId } ] return shuffle(rawAnswers) }, [props.result, correctId, incorrectIds])
内容的提问来源于stack exchange,提问作者Jake Clifford
相关产品推荐
相关产品推荐

