为何React状态未变更,点击按钮后组件仍二次渲染并打印日志?
案例一:相同状态值触发组件二次渲染的原因
点击按钮第二次时,App组件似乎会进行二次渲染,但按道理状态设置为相同值时不应变更,为何会出现这种情况?
import React, { useState } from "react"; const App = () => { const [someState, changeSomeState] = useState(null); console.log(someState); console.log('App component rendered'); return ( <> <button onClick={() => { changeSomeState(6666); }} > Button in App </button> </> ); }; export default App;
原因
- 这是React开发模式下Strict Mode(严格模式)的特性:严格模式会重复执行一次渲染逻辑,用来检测代码中的非幂等操作、潜在副作用等问题,帮你提前发现bug。
- 生产模式下,这种额外渲染会被移除,此时第二次点击按钮,因为状态值和当前值完全相同,React会直接跳过组件重渲染。
- 如果你在项目的根组件外层包裹了
<React.StrictMode>,去掉它就能在开发模式下看到正常的渲染次数。
案例二:父组件二次渲染但子组件仅渲染一次的原因
点击按钮后,App组件出现二次渲染,但嵌套在App内的Test组件仅渲染一次,这是为什么?
Test组件代码(每次重渲染都会执行console.log):
import React from "react"; const Test = () => { console.log("Test component rendered"); return <div>Test</div>; }; export default Test;
App组件代码:
import React, { useState } from "react"; import Test from "./Test"; const App = () => { const [someState, changeSomeState] = useState(null); console.log(someState); return ( <> <Test /> <button onClick={() => { changeSomeState(6666); }} > Button in App </button> </> ); }; export default App;
原因
- React默认会做浅比较优化:当父组件重渲染时,React会检查子组件的props是否发生变化。如果子组件没有接收任何props,或者props和上一次完全一致,React会判定子组件的输出不会改变,直接复用之前的渲染结果,不会再次执行子组件的函数体。
- 这里的Test组件既没有接收props,也没有依赖父组件的任何状态或上下文,所以React直接跳过了它的重渲染。
- 要是想让Test组件跟着父组件重渲染,可以给它传递一个动态变化的props(比如
<Test value={someState} />),或者给它设置一个随状态变化的key(<Test key={someState} />),这时父组件重渲染时Test也会跟着重新执行。
内容的提问来源于stack exchange,提问作者Bobi
相关产品推荐
相关产品推荐

