为何React useEffect设相同状态触发组件重执行,事件处理器却不会?
React中useEffect内设置相同state导致重渲染的原因
现象描述
在测试场景中:
- 点击按钮触发
handleClick修改state,state更新后useEffect钩子执行 - 在
useEffect内调用setNumOfClicks(numOfClicks)(设置与当前state相同的值),会导致Counter组件重新执行 - 但如果直接在事件处理器中调用相同值的
setState,组件并不会重渲染
底层逻辑解释
这核心是React的批量更新机制和useEffect的执行上下文差异导致的:
合成事件中的批量更新
React对按钮onClick这类合成事件内的setState会做批量处理:先收集所有setState操作,等事件处理完成后统一执行更新。过程中会对比state新旧值,若值无变化则直接跳过更新,不会触发组件重渲染。useEffect的异步执行上下文
useEffect是在组件渲染完成、DOM更新后执行的副作用,它的执行时机脱离了React合成事件的批量更新上下文,属于独立的异步执行流程。在这个上下文里调用setState,React会立即触发更新流程——哪怕新值和旧值完全相同,也不会跳过这次更新触发,会让组件重新执行一次(不过因为state值没变化,最终DOM不会有更新)。
测试代码
import React from "react"; import ReactDOM from "react-dom/client"; function App(){ return( <> <h1>Counters</h1> <section> <Counter /> </section> </> ); } function Counter(props){ console.log("Inside Counter Function...."); const [numOfClicks,setNumOfClicks] = React.useState(0); console.log("numOfClicks = "+numOfClicks); React.useEffect(()=>{ console.log("In useEffect"); console.log("useEffects => numOfClicks = "+numOfClicks); setNumOfClicks(numOfClicks); },[numOfClicks]); function handleClick(){ setNumOfClicks(numOfClicks+1); console.log("Inside handle Click...."); } return( <article> <h2>Counter {props.name}</h2> <p>You clicked {numOfClicks} times</p> <button className="button" onClick={handleClick}> Click Me </button> </article> ); } const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<App/>);
内容的提问来源于stack exchange,提问作者to-find
相关产品推荐
相关产品推荐

