讨论#React
一个 useEffect 引发的渲染风暴:排查笔记
昨天线上页面突然出现卡顿,排查下来元凶是一个看似无害的 useEffect。
事故现场
useEffect(() => {
setFiltered(list.filter((item) => item.visible));
}, [list]); // 看起来没问题?
问题出在 list 是父组件每次 render 新建的数组,引用每次都变,effect 每次都跑,setFiltered 又触发子树重渲染,循环放大。
修复
派生状态根本不需要 useEffect:
const filtered = useMemo(() => list.filter((item) => item.visible), [list]);
更彻底的做法是让父组件用 useMemo 稳定 list 的引用。
教训
- 派生状态优先用
useMemo,不要useEffect + setState useEffect只用于真正的副作用:订阅、请求、DOM 操作- React DevTools 的 Profiler 一眼就能看到渲染次数异常