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

如何使用Jotai将Firebase获取的数据存储到store的atom中?

Jotai全局存储Firebase拉取数据实现方案

你当前的写法已经具备基础的写入atom能力,但存在初始值缺失、逻辑散落在组件、边界场景未兼容、冗余代码多的问题,按以下步骤调整即可实现全局store存储Firebase数据的需求。


第一步:调整store文件代码

将数据拉取逻辑和atom定义统一收敛在store层,给atom设置合理初始值,兼容异常边界场景:

import firebase from "@firebase/app";
import "@firebase/database";
import { Alert } from "react-native";
import { atom } from "jotai";

// 全局存储剧集数据的atom,初始值设为空数组,避免首次渲染判断异常
export const watchSeriesJotai = atom([]);

/**
 * 拉取Firebase剧集数据并更新全局store
 * @param {Function} setAtom jotai的写入方法
 */
export const fetchWatchSeries = async (setAtom) => {
  try {
    // firebase.auth()为同步方法,无需加await
    const { currentUser } = firebase.auth();
    // 未登录场景兜底
    if (!currentUser) {
      setAtom([]);
      return;
    }

    const dbRef = firebase.database().ref(`/users/${currentUser.uid}/series`);
    const snapshot = await dbRef.once("value");
    const rawSeries = snapshot.val() || {}; // 无数据时兜底为空对象,避免Object.keys报错

    // 转换数据格式,补充id字段
    const formattedSeries = Object.keys(rawSeries).map((id) => ({
      ...rawSeries[id],
      id
    }));

    console.warn("拉取到的剧集数据:", formattedSeries);
    // 将处理后的数据写入全局atom
    setAtom(formattedSeries);
    return formattedSeries;
  } catch (error) {
    Alert.alert("数据拉取失败", error?.message || "未知错误");
    return [];
  }
};

第二步:调整组件调用逻辑

清理冗余导入,优化atom读写方式,增加页面聚焦时的自动刷新逻辑:

import React, { useEffect } from "react";
import { ViewLoading, Loading, ViewList, ViewTop, ViewBottom } from "./styles";
import { useIsFocused } from "@react-navigation/native";

import SerieCard from "../../components/SerieCard";
import AddSerieCard from "../../components/AddSerieCard";

import { watchSeriesJotai, fetchWatchSeries } from "../../storeJotai/event";
import { useAtomValue, useSetAtom } from "jotai";

const isEven = (number) => number % 2 === 0;

export const ListSeries = ({ navigation }) => {
  // 拆分读写操作,比直接用useAtom性能更好
  const series = useAtomValue(watchSeriesJotai);
  const setSeries = useSetAtom(watchSeriesJotai);
  const isPageFocused = useIsFocused();

  useEffect(() => {
    // 页面聚焦时拉取最新数据,保证切回页面时内容同步
    if (isPageFocused) {
      fetchWatchSeries(setSeries);
    }
  }, [isPageFocused, setSeries]);

  return (
    <>
      {series.length === 0 ? (
        <ViewLoading>
          <Loading size="large" color="light-blue" />
        </ViewLoading>
      ) : (
        <ViewList
          data={[...series, { isLast: true }]}
          renderItem={({ item, index }) =>
            item.isLast ? (
              <AddSerieCard
                isFirstColumn={isEven(index)}
                onNavigate={() => navigation.navigate("SerieForm")}
              />
            ) : (
              <SerieCard
                serie={item}
                isFirstColumn={isEven(index)}
                onNavigate={() =>
                  navigation.navigate("SerieDetail", { serie: item })
                }
              />
            )
          }
          keyExtractor={(item) => item.id || "add-card"}
          numColumns={2}
          showsVerticalScrollIndicator={false}
          ListHeaderComponent={<ViewTop />}
          ListFooterComponent={<ViewBottom />}
        />
      )}
    </>
  );
};

关键调整说明

  • 给atom设置初始空数组,解决原无初始值导致的首次渲染判断逻辑异常问题
  • 所有数据拉取、格式转换、store更新逻辑统一收敛在store层,后续任意组件需要刷新剧集数据,直接调用fetchWatchSeries传入对应set方法即可,无需重复编写转换逻辑
  • 兼容未登录、无剧集数据、请求报错等边界场景,避免白屏报错
  • 组件拆分atom读写操作,减少不必要的重渲染
  • 增加页面聚焦触发拉取的逻辑,新增/编辑/删除剧集后切回列表页能自动同步最新数据
  • 清理了原组件中未使用的冗余导入,优化代码体积
  • 补全keyExtractor兜底逻辑,避免列表渲染key警告

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:24:17