React useRef/useEffect 阻止effect首次渲染执行的实现问题
问题原因
你的核心实现思路在非严格模式的生产环境下可以正常运行,开发环境出现首次挂载就执行的问题,是React 18+ 严格模式(Strict Mode)的特殊机制导致的:
- 开发环境开启严格模式时,组件首次挂载阶段React会主动执行两轮副作用流程:挂载执行effect → 执行effect清理 → 重新挂载执行effect,目的是提前暴露缺失清理逻辑的副作用bug
- 你的原代码没有编写effect清理逻辑,第一轮effect执行时会把
isMounted.current设为true,第二轮模拟重挂载执行effect时,ref保存的标记已经是true,就会直接触发fetchData(),表现为首次挂载就执行了逻辑。
本质上用isMounted标记跳过首次渲染的方案,是绕开了「useEffect默认首次执行」的默认行为,并没有直接贴合你的核心需求:仅在success值发生变化时执行逻辑,这类标记方案很容易受React生命周期执行规则变化的影响。
可靠实现方案
直接通过ref记录上一次的success值,每次effect执行时对比前后值,只有值确实发生变化时才执行业务逻辑,完全绕开挂载次数、严格模式的影响,完全匹配需求:
// 初始化时存储success的初始值 const prevSuccess = useRef(success); useEffect(() => { // 当前值和上一次记录的值不一致,说明是success变化触发的执行 if (prevSuccess.current !== success) { fetchData(); // 执行完成后更新ref存储的旧值 prevSuccess.current = success; } }, [success]);
这个实现的表现完全符合预期:
- 首次挂载时,ref存储的值和当前
success值完全相等,不会执行fetchData - 后续每次
success更新,前后值不相等时才会触发业务逻辑 - 不受严格模式双调用、React版本生命周期规则调整的影响
内容的提问来源于stack exchange,提问作者ERLay
相关产品推荐
相关产品推荐

