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

React Native结合RealmDB时useEffect触发已卸载组件更新state警告问题

问题根因与修复方案

核心问题原因

  • 闭包陷阱:你使用didMount状态判断组件挂载状态的逻辑完全不生效。由于useEffect的依赖项是空数组,loadProducts异步函数创建时捕获的didMount永远是初始值false,后续执行setDidMount(true)不会更新闭包内的变量值,组件卸载后setProducts仍然会执行,直接触发警告。
  • Realm集合特性:realm.objects()返回的是Realm的活响应式集合对象,不是普通静态数组,哪怕组件卸载后,如果Realm内的Product数据发生变更,这个集合会自动触发更新,也可能导致已卸载组件的state更新。

修复后代码

import { useRef, useState, useEffect } from 'react';

// 类型定义根据你的实际业务调整
type Product = {
  id: number;
  // 其他字段...
};

const [products, setProducts] = useState<Product[]>([]);
// 用ref存储挂载状态,不受闭包影响,可实时获取最新值
const isMountedRef = useRef<boolean>(true);

useEffect(() => {
  async function loadProducts() {
    const realm = await getRealm();

    try {
      const realmProducts = realm
        .objects<Product>('Product')
        .sorted('id', true);
      // 执行state更新前先判断组件是否仍挂载
      if (!isMountedRef.current) return;
      // 将Realm响应式集合转为普通静态数组再赋值给state
      setProducts([...realmProducts]);
    } catch (err) {
      console.error(err);
    } finally {
      // 组件已卸载的情况下关闭realm实例,释放资源
      if (!isMountedRef.current) {
        realm.close();
      }
    }
  }

  loadProducts();

  return function cleanup() {
    // 组件卸载时标记挂载状态为false
    isMountedRef.current = false;
  };
}, []);

额外优化建议

如果项目允许引入@realm/react官方封装库,可以直接使用内置的useQuery钩子,不需要手动处理异步查询和挂载状态,官方已经做了内存泄漏防护,使用更简洁:

import { useQuery } from '@realm/react';

// 组件内直接调用,自动响应数据变化,无泄漏风险
const products = useQuery(Product, (collection) => collection.sorted('id', true));

内容的提问来源于stack exchange,提问作者Victor Souto Soares

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:57:04