React函数组件中特定state变化时如何阻止答案重新随机排序的重渲染
解决方案
问题根本原因
你把随机排序逻辑直接写在了JSX渲染代码中,每次组件触发重渲染(包括选中答案更新selectedAnswerId、selectedAnswer两个state的场景),都会重新执行一次随机排序逻辑,导致选项顺序被再次打乱。
修复方案
方案1:使用useMemo缓存打乱后的选项(推荐)
仅在切换题目时重新随机排序选项,选中答案等其他场景触发重渲染时直接复用缓存的排序结果:
首先在组件内定义缓存变量:
import { useMemo } from 'react' // 仅当currentQuestion变化时,才重新生成打乱后的选项 const shuffledOptions = useMemo(() => { return questions[currentQuestion].options .slice(0, questions[currentQuestion].options.length - 1) .sort(() => Math.random() - 0.5) }, [currentQuestion])
然后把原JSX中的排序逻辑替换为直接遍历shuffledOptions,同时注意把列表key从index替换为answer.id,避免React Diff时出现组件复用异常:
{shuffledOptions.map((answer) => ( <TouchableOpacity onPress={selectedAnswerHandler.bind( this, answer.id, answer.answerText )} key={answer.id} > {/* 原有内部View、Text样式逻辑保持不变 */} <View style={ selectedAnwserId === answer.id ? styles.selectedAnswerTab : styles.answerTab } > <Text style={ selectedAnwserId === answer.id ? [styles.answerText, { color: color.secondaryColor }] : styles.answerText } > {answer.answerText} </Text> </View> </TouchableOpacity> ))}
方案2:将打乱后的选项存入state
和useMemo效果一致,适合需要后续手动修改选项排序的场景:
import { useState, useEffect } from 'react' const [shuffledOptions, setShuffledOptions] = useState([]) // 切换题目时重新打乱选项 useEffect(() => { const newOptions = questions[currentQuestion].options .slice(0, questions[currentQuestion].options.length - 1) .sort(() => Math.random() - 0.5) setShuffledOptions(newOptions) }, [currentQuestion])
渲染逻辑和方案1完全一致,直接遍历shuffledOptions即可。
附加优化建议
你当前使用的sort(() => Math.random() - 0.5)不是公平的洗牌算法,不同位置选项的排序概率会有偏差,如果对排序公平性要求较高,可以替换为Fisher-Yates洗牌算法:
const shuffleArray = (array) => { const newArr = [...array] for (let i = newArr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [newArr[i], newArr[j]] = [newArr[j], newArr[i]] } return newArr }
使用时把排序部分替换为shuffleArray(待排序数组)即可。
内容的提问来源于stack exchange,提问作者Wahas Ali Mughal
相关产品推荐
相关产品推荐

