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

React Native中Supabase实时数据订阅时状态重置问题求助

问题解决:Supabase实时订阅导致React State重置

问题根源

你的代码存在闭包陷阱:useEffect依赖数组为空,订阅回调和ReplaceObj函数捕获的是组件初始渲染时的data状态(空数组)。当数据库更新触发回调时,ReplaceObj里的data始终是初始空数组,执行setData([...filteredList, newObj])会把状态重置成仅含新对象的数组,而非基于最新已有数据更新。

另外,当前代码只处理了payload.new的情况,未区分增、删、改不同事件类型,逻辑不完整。

修复方案

1. 使用函数式更新setData

函数式更新可基于最新状态值修改,避免闭包带来的旧引用问题。

2. 区分数据库事件类型

Supabase实时回调返回的payload.event包含INSERT/UPDATE/DELETE,对应增、改、删操作,需针对性处理。

修复后的代码

const [data, setData] = useState<IProduct[]>([]);

useEffect(() => {
  // 初始化获取数据
  const fetchInitialData = async () => {
    const { data: responseData } = await supabase
      .from('Products')
      .select('*');
    if (responseData) {
      setData(responseData as IProduct[]);
    }
  };
  fetchInitialData();

  // 订阅实时更新
  const productChannel = supabase
    .channel('custom-all-channel')
    .on(
      'postgres_changes',
      { event: '*', schema: 'public', table: 'Products' },
      (payload) => {
        switch (payload.event) {
          case 'INSERT':
            // 新增:添加新对象到数组
            setData(prev => [...prev, payload.new as IProduct]);
            break;
          case 'UPDATE':
            // 更新:替换对应id的对象
            setData(prev => 
              prev.map(item => 
                item.id === payload.new.id ? payload.new as IProduct : item
              )
            );
            break;
          case 'DELETE':
            // 删除:移除对应id的对象
            setData(prev => 
              prev.filter(item => item.id !== payload.old.id)
            );
            break;
        }
      }
    )
    .subscribe();

  return () => productChannel.unsubscribe();
}, []);

额外说明

  • 禁用RLS不会导致state重置,问题完全由React状态更新的闭包逻辑引发。
  • 函数式更新setData(prev => ...)中,prev始终是当前最新状态值,规避了闭包捕获旧值的问题。
  • 移除单独的ReplaceObj函数,直接在回调内处理不同事件,逻辑更清晰,同时避免闭包问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 19:42:20