You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React 18严格模式:useMemo创建实例后如何合规清理?

解决React 18严格模式下实例创建与清理的问题

在React 18严格模式的开发环境中,组件会经历「挂载→立即卸载→重新挂载」的流程,用来检测未正确清理的副作用。你之前用useMemo创建实例、useEffect清理的方式,会导致第一次卸载时销毁实例,但第二次挂载时复用已销毁的实例(因为useMemo依赖空数组,不会重新执行),从而引发异常。

改用useState的方案会触发额外渲染,还会返回初始空值,不符合需求。以下是不影响性能、适配严格模式的解决方案:

实现方案

使用useRef存储实例与销毁状态,结合渲染阶段的惰性初始化和useEffect的清理逻辑,既保证实例在渲染时即可使用,又能在严格模式下正确重建实例:

function useFoo() {
  const fooRef = useRef({
    instance: null,
    isDestroyed: false
  });

  // 渲染阶段惰性初始化:实例不存在或已销毁时,创建新实例
  if (!fooRef.current.instance || fooRef.current.isDestroyed) {
    fooRef.current.instance = createFoo();
    fooRef.current.isDestroyed = false;
  }

  useEffect(() => {
    const currentInstance = fooRef.current.instance;
    return () => {
      // 清理时销毁当前实例,并标记为已销毁
      currentInstance.destroy();
      fooRef.current.isDestroyed = true;
    };
  }, []);

  return fooRef.current.instance;
}

原理说明

  1. 无渲染触发的状态存储:useRef的修改不会触发组件重渲染,避免额外性能损耗。
  2. 始终返回有效实例:渲染阶段直接检查实例状态,确保返回的实例不会是空值或已销毁的实例。
  3. 适配严格模式:严格模式下第一次卸载时,清理函数会销毁实例并标记状态;第二次渲染时会自动创建新实例,保证后续使用的是可用实例。

注意事项

  • 如果createFoo包含副作用(比如创建DOM元素、订阅事件),开发环境下严格模式会触发两次实例创建,但第一次的实例会在清理函数中销毁,仅在开发阶段存在临时资源占用,生产环境不会有此问题。
  • 确保createFoo可以被安全调用多次,每次调用都能生成独立的实例。

内容的提问来源于stack exchange,提问作者Seba Kerckhof

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 18:25:30