React中useEffect依赖值从1变为0时未触发执行的问题排查
useEffect依赖变更后未触发执行问题排查
问题场景
verticesCount从1变回0触发组件重渲染后,绑定该值作为依赖的useEffect既没有执行清理函数,也没有执行新的副作用逻辑,相关代码和日志如下:
示例代码
const verticesCount = selectionProvider.verticesSelectionProvider.count; console.log('RENDER ---> COUNT = ', verticesCount); useEffect(() => { console.log('EFFECT : COUNT UPDATED ---> COUNT = ', verticesCount); return () => console.log('USEEFFECT:CLEANUP'); }, [verticesCount]);
控制台日志
1: RENDER ---> COUNT = 0 2: EFFECT : COUNT UPDATED ---> COUNT = 0 3: RENDER ---> COUNT = 1 4: USEEFFECT:CLEANUP 5: EFFECT : COUNT UPDATED ---> COUNT = 1 6: RENDER ---> COUNT = 0
核心原因
首先明确React useEffect的执行规则:
useEffect的清理函数、副作用逻辑都属于commit阶段的执行逻辑,只有组件render阶段执行完成、虚拟DOM diff结束、DOM更新提交完成后才会按顺序执行。只要render流程中途终止、没有顺利进入commit阶段,所有effect相关逻辑都不会触发。
从日志可以看出,verticesCount从0到1的更新流程完全符合React执行预期:初始渲染提交后执行初始effect,count更新为1的渲染提交后,先执行上一轮的清理函数,再执行新的副作用。
而count从1切回0时只打印了render日志,没有后续effect相关输出,说明这次渲染在commit阶段之前就被终止了,常见触发原因按概率从高到低排列:
- render阶段抛出未捕获的运行时错误
打印render日志的代码在组件函数靠前位置,如果这行代码执行后,组件后续的逻辑(其他hook执行、JSX计算、变量取值等)抛出了运行时错误,React会直接终止本次渲染流程,不会进入commit阶段,自然不会触发任何effect逻辑。这类问题直接查看浏览器控制台的错误面板即可定位,是该类异常最高发的诱因。 - React并发调度下的无效渲染被废弃
React 18+的并发渲染模式下,低优先级的渲染任务可能被高优先级更新打断,被打断的渲染结果会被直接废弃、不会提交到DOM,对应的effect逻辑自然也不会执行。这种情况属于React正常调度行为,不需要额外修复。 - Hook调用顺序不匹配
如果本次渲染中,该useEffect之前存在条件调用Hook的写法(比如在if判断块内调用useState、useMemo、useEffect等),会导致React的Hook链表匹配错乱,无法关联到之前挂载的effect实例,也会出现effect不执行的问题,这类场景下控制台一般会抛出明确的Hook调用顺序错误提示。
内容的提问来源于stack exchange,提问作者Zakaria
相关产品推荐
相关产品推荐

