React.js 父组件传随机值作为props时控制台输出值不一致问题
两个异常现象的本质
日志数量和预期不符、父子组件打印的随机值对不上,全部由React 18的默认执行逻辑、随机值的生成位置导致,不存在语法层面的代码错误。
日志数量异常的原因
- 目前观察到控制台总共仅打印2条日志,是因为项目没有在入口文件包裹
React.StrictMode:React首次挂载页面时,会执行1次App组件的函数体生成1条日志,再渲染传入了props的Board组件、执行1次Board的函数体生成1条日志,累计刚好2条。 - 如果在入口文件(一般为
main.jsx)外层加上<StrictMode>包裹整个应用,开发环境下React会自动把所有函数组件的函数体执行2次,用来提前暴露组件内的意外副作用,这时候会看到总共4条日志。这个双执行的特性仅在开发环境生效,生产构建不会触发重复执行。
随机值打印不一致的原因
当前代码将Math.random()直接写在App的组件函数体内部,组件函数每执行一次,都会从头重新跑一遍函数里的所有逻辑,生成一个全新的随机数,再把这个新值传给子组件。
以开启StrictMode后的双执行流程为例,实际的执行顺序会是:
- 第一次执行App函数体:生成随机数0.23,将0.23传给Board组件,执行第一次Board函数体,打印0.23
- React触发开发模式下的第二次组件校验执行:再次运行App的函数体,重新生成随机数0.79,将0.79传给再次执行的Board组件,第二次执行Board函数体,打印0.79
这种执行顺序下,控制台的4条日志会依次输出两个App的打印、两个Board的打印,如果截取片段观察,就会觉得父子组件打印的值对不上。
修复方案
如果需要让随机数只生成一次、全链路共用同一个固定值,只需要把随机数的生成逻辑从组件普通函数体,移到仅执行一次的初始化位置即可:
用useState的惰性初始化生成随机数,初始化函数只会在组件首次挂载时执行一次,后续不管组件重渲染多少次都不会重新执行。
修改后的App.js参考代码:
import { useState } from 'react'; import Board from './Board'; function App() { // 括号内的初始化逻辑仅在组件首次挂载时执行 const [rand] = useState(() => Math.random()); console.log('App打印值:', rand); return ( <div className="App"> <Board rand={rand} /> </div> ); } export default App;
这种写法下,不管组件因为开发模式双执行、还是后续业务逻辑触发重渲染,拿到的rand都是同一个值,子组件收到的props也不会出现前后不一致的问题。
内容的提问来源于stack exchange,提问作者Himanshu Sharma
相关产品推荐
相关产品推荐

