React组件意外重复渲染:BazaarPage为何打印4次数据?
React组件渲染次数超出预期的问题分析
你的认知误区
你默认React只会在初始加载和state更新时各渲染一次组件,但忽略了React开发环境下的Strict Mode机制,以及组件渲染的触发逻辑——只要父组件渲染,子组件(满足条件渲染时)就会跟着渲染,而不是只在props首次变化时渲染。
导致BazaarPage打印4次的核心原因
1. 开发环境Strict Mode的双重执行
如果你的项目开启了Strict Mode(几乎所有React初始化项目默认都会开启,入口文件里的<React.StrictMode>标签),开发环境下React会刻意重复执行:
- 组件的顶层代码(包括console.log)
- useEffect、useReducer等钩子的逻辑
- 组件的渲染过程
这种情况下:
- App初始加载会被执行2次,此时data为null,BazaarPage不渲染
- 接口请求完成,data更新后,App又会被执行2次,每次都满足
data && <BazaarPage />,所以BazaarPage的顶层console.log会打印2×2=4次。
2. 可能的额外渲染触发点
如果去掉Strict Mode后还是有多余渲染,要检查这些点:
- App组件的父组件(如果存在)是否发生了不必要的渲染
- useEffect的依赖项是否设置错误:比如依赖项包含了每次渲染都会生成新引用的对象/函数,导致useEffect重复执行,state被多次更新
- 接口是否返回了重复响应:比如接口因为缓存或重试机制返回了两次相同数据,触发state多次更新
验证与解决方法
- 验证Strict Mode影响:注释掉入口文件里的
<React.StrictMode>,重新运行项目,此时App应该渲染2次,BazaarPage的log会变成1次(如果没有其他额外渲染的话)。 - 精准控制log时机:如果只想在data变化时打印,不要把log放在BazaarPage的顶层,改用
useEffect:
这样只会在data首次传入或更新时打印,和组件渲染次数解绑。// BazaarPage组件内部 useEffect(() => { console.log(data); }, [data]); - 排查额外渲染:在App组件顶层加
console.log('App渲染'),统计实际渲染次数,定位多出来的渲染是由什么触发的(比如父组件渲染、state重复更新等)。
内容的提问来源于stack exchange,提问作者Nate Baker
相关产品推荐
相关产品推荐

