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
相关产品推荐
相关产品推荐

