为何useEffect在组件重新渲染前执行?React计数器问题求助
React计数器alert弹窗与DOM更新顺序问题解决
问题根源
React状态更新后,会先完成DOM的渲染更新,再执行useEffect钩子。但alert是同步阻塞的API,一旦执行就会暂停浏览器所有后续任务(包括DOM渲染),所以即便useEffect在渲染后触发,alert弹出时DOM还没来得及更新,直到你关闭弹窗,浏览器才会继续完成h1的数值更新。
另外你代码里的prev变量是普通let声明,每次组件重新渲染都会被重置为0,完全起不到保存前值的作用,还错误地加到了useEffect的依赖数组里,属于冗余代码。
修复代码
把alert放到setTimeout中,让它进入宏任务队列,等当前渲染周期结束、DOM更新完成后再执行:
import { useEffect, useState } from "react"; export default function App() { const [number, setNumber] = useState(0); useEffect(() => { if (number !== 0) { setTimeout(() => { alert("Number changed to " + number); }, 0); } }, [number]); return ( <> <h1>{number}</h1> <button onClick={() => setNumber(n => n + 5)}> +5 </button> </> ); }
关键说明
setTimeout(fn, 0)不会真的等0秒,而是把回调推迟到当前所有同步任务(包括React的DOM更新)完成后再执行,这样就能保证h1的数值先更新,再弹出alert。- 移除了无用的
prev变量,避免不必要的useEffect触发和代码混淆。
内容的提问来源于stack exchange,提问作者elmor6942
相关产品推荐
相关产品推荐

