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

Firebase中snapshot赋值给useState返回undefined问题排查

问题根因

你的代码有三个核心问题导致异常:

  • useEffect依赖数组为空,首次执行时currentUser还未从鉴权上下文加载完成,此时currentUser?.uid为undefined,实际请求的数据库路径是users/undefined/likes,自然读不到数据,触发"No data available"提示。
  • 状态更新逻辑位置错误:你在forEach循环内部反复调用setData,还将整个results数组拼接到之前的状态里,最终会生成嵌套结构的错误数组;同时React状态更新是异步批处理的,你在调用setData后立刻打印data,拿到的永远是更新前的旧值,看不到最新结果。
  • 你在数据库请求前加了不必要的return,将请求Promise直接作为useEffect的返回值,useEffect的返回值仅接受清理函数,这个写法会导致逻辑执行不符合预期。
修复后代码
// 在UI上展示用户点赞的图片
export const useShowLikedImageFromDB = () => {
  const [data, setData] = useState([]);
  const currentUser = useAuth();

  useEffect(() => {
    // 未获取到用户ID时终止执行,不发送无效请求
    if (!currentUser?.uid) return;

    const results = [];
    const dbRef = ref(getDatabase());

    get(child(dbRef, `users/${currentUser.uid}/likes`))
      .then((snapshot) => {
        if (snapshot.exists()) {
          snapshot.forEach((item) => {
            results.push(item.val());
          });
          // 所有数据收集完成后,一次性更新状态
          setData(results);
        } else {
          setData([]);
          console.log("No data available");
        }
      })
      .catch((error) => {
        console.error(error);
      });
  // 将currentUser加入依赖数组,用户信息加载完成后自动重新拉取数据
  }, [currentUser]);

  return { data };
};
注意事项
  • 不要在调用setData的同步代码块里立刻打印state值,受React异步更新机制影响,这里拿到的永远是旧值。要观测最新state,可以单独写一个依赖为data的useEffect执行打印,或者直接通过React开发者工具查看组件状态。
  • 避免在循环中反复调用setData,会触发多次无意义的组件重渲染,拉低性能,等所有数据处理完成后一次性更新即可。
  • 如果你的组件存在提前卸载的场景,可以加一个挂载标记,避免组件卸载后还调用setData触发内存泄漏警告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:01:12