React调用Math.random()多次后为何反复返回同一固定数值
问题现象
在React中使用useState管理状态时,累计触发getRandomNumbers函数15-20次后,函数不再生成随机结果,会反复返回同一个数值,相关实现代码如下:
import {useState} from "react"; function App() { const [numbers, setNumbers] = useState(['1','2','3','4', '5']); function getRandomNumbers(){ let result = []; for(let i = 0; i < numbers.length; i++){ result.push(numbers[Math.floor(Math.random() * numbers.length)]); } // setting new array in numbers setNumbers(numbers => result); } const displayNumbers = numbers.map((no, i) => { return ( <div key={i}>{no}</div> ); }); return ( <div> {displayNumbers} <br/> <button type='button' onClick={() => getRandomNumbers()}>Click</button> </div> ); } export default App;
错误原因
代码核心逻辑问题是:每次生成随机数的采样源是当前state中存储的numbers数组,而非初始固定的['1','2','3','4','5']。
每次点击按钮生成新数组时,都是从上一次生成的数组里随机抽元素,随着点击次数增加,数组内的元素种类会大概率逐渐收敛:
- 比如某次随机生成的新数组全是
'3',那后续所有随机采样的源数组就只有'3'这一个值 - 无论后续触发多少次随机逻辑,
Math.random()取到的数组元素永远是'3',就会出现反复返回同一个值的现象
这个收敛过程的触发概率随点击次数升高,通常十几次到二十次点击就会复现。
修复方法
如果需求是每次都从初始固定的5个数字里随机抽取生成新数组,只需要把固定的候选采样池单独抽离,不要用动态变化的state值作为采样源即可,修复后代码如下:
import {useState} from "react"; // 固定随机数候选池,不受state变化影响 const NUMBER_CANDIDATES = ['1','2','3','4', '5']; function App() { const [numbers, setNumbers] = useState([...NUMBER_CANDIDATES]); function getRandomNumbers(){ let result = []; for(let i = 0; i < NUMBER_CANDIDATES.length; i++){ result.push(NUMBER_CANDIDATES[Math.floor(Math.random() * NUMBER_CANDIDATES.length)]); } setNumbers(result); } const displayNumbers = numbers.map((no, i) => { return ( <div key={i}>{no}</div> ); }); return ( <div> {displayNumbers} <br/> <button type='button' onClick={() => getRandomNumbers()}>Click</button> </div> ); } export default App;
内容的提问来源于stack exchange,提问作者noBoom
相关产品推荐
相关产品推荐

