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

Firebase加载场景下页面刷新后购物车数据丢失问题求助

问题:页面刷新后购物车数据无法显示(Firebase加载延迟导致)

从Firebase加载数据时,页面刷新会出现加载延迟,导致购物车无法展示已添加的商品数据。但用相同流程存储用户数据时功能正常,控制台能正常获取注册用户信息,需要解决购物车数据刷新后不显示的问题。

商品添加到购物车的组件代码

import { motion } from "framer-motion";
import React, { useEffect, useRef, useState } from "react";
import { MdShoppingBasket } from "react-icons/md";
import { actionType } from "../context/reducer";
import { useGlobalState } from "../context/stateProvider";
import NotFound from "../img/NotFound.svg";
const RowContainer = ({ flag, data, scrollValue }) => {
  const [{ cartItems }, dispatch] = useGlobalState();
  const [items, setItems] = useState([]);

  const rowContainer = useRef();
  const addToCart = () => {
    dispatch({
      type: actionType.SET_CARTITEMS,
      cartItems: items,
    });
    localStorage.setItem("cartItems", JSON.stringify(items));
  };
  useEffect(() => {
    addToCart();
  }, [items]);
  useEffect(() => {
    rowContainer.current.scrollLeft += scrollValue;
  }, [scrollValue]);
  return (
    <div
      ref={rowContainer}
      className={`w-full my-12 flex items-center ${
        flag
          ? "overflow-x-scroll scrollbar-none scroll-smooth"
          : "overflow-x-hidden flex-wrap justify-center"
      }`}
    >
      {data && data.length > 0 ? (
        data.map((item) => {
          const { id, price, imageURL, calories, title } = item;
          return (
            <div
              key={id}
              className="w-350 min-w-[300px] md:min-w-[380px] md:my-10  backdrop-blur-lg mx-1 my-2 lg:mx-2  "
            >
              <div className="w-full flex flex-row items-center justify-between bg-white rounded-lg drop-shadow-lg py-2 px-4 hover:bg-whiteAlpha min-h-[150px]">
                <motion.img
                  whileHover={{ scale: 1.2 }}
                  src={imageURL}
                  alt="img"
                  className="w-30 max-h-40 -mt-8 duration-100  drop-shadow-2xl"
                />
                <div className="flex flex-col items-end justify-end gap-4">
                  <motion.div
                    whileTap={{ scale: 0.75 }}
                    className="w-8 h-8 rounded-md bg-orange-500 hover:bg-orange-600 "
                    onClick={() => setItems([...new Set(cartItems), item])}
                  >
                    <MdShoppingBasket className="text-white text-2xl m-1" />
                  </motion.div>
                  <div className=" w-full">
                    <p className="text-gray-800 md:text-lg text-base text-right">
                      {title}
                    </p>
                    <p className="text-sm text-gray-500 text-right">
                      <span className="text-orange-600">$</span> {price}
                    </p>
                  </div>
                </div>
              </div>
            </div>
          );
        })
      ) : (
        <div className="w-full flex flex-col items-center justify-center">
          <img src={NotFound} className="h-340" alt="" />
          <p className="text-center my-2 text-xl text-red-500">No data found</p>
        </div>
      )}
    </div>
  );
};
export default RowContainer;

获取购物车数据的代码

export const fetchCart = () => {
    const cartInfo =
      localStorage.getItem("cartItems") !== "undefined"
        ? JSON.parse(localStorage.getItem("cartItems"))
        : localStorage.clear();
    return cartInfo ? cartInfo : [];
  };

问题分析与修复方案

核心问题

  1. 全局状态未优先读取本地存储:页面刷新时,全局购物车状态初始为空,没有先加载localStorage里的缓存数据,Firebase加载延迟期间购物车自然无内容。
  2. 添加逻辑冗余且存在错误:依赖items状态触发更新,初始为空时会覆盖本地已有数据;用Set去重对对象无效(对象引用不同),无法正确避免重复添加。
  3. fetchCart函数逻辑漏洞:判断条件错误,当localStorage无cartItems键时返回null,不会等于字符串"undefined",导致错误执行localStorage.clear()清空所有本地数据。

具体修复步骤

  1. 修正全局状态初始化
    在全局状态的初始值中直接调用fetchCart(),确保页面刷新后先加载本地缓存的购物车数据:
// stateProvider.js 示例代码
import { fetchCart } from './对应路径';

const initialState = {
  cartItems: fetchCart(),
  // 其他状态...
};
  1. 修复fetchCart函数
    修改判断逻辑,正确处理本地存储无数据的情况:
export const fetchCart = () => {
  const cartInfo = localStorage.getItem("cartItems");
  return cartInfo ? JSON.parse(cartInfo) : [];
};
  1. 重构添加购物车逻辑
    去掉冗余的items状态和依赖它的副作用,直接在点击时更新全局状态和本地存储,同时通过商品id实现正确去重:
// RowContainer组件修改后的核心代码
const RowContainer = ({ flag, data, scrollValue }) => {
  const [{ cartItems }, dispatch] = useGlobalState();
  const rowContainer = useRef();

  const handleAddToCart = (item) => {
    // 通过id判断商品是否已存在
    const isExist = cartItems.some(cartItem => cartItem.id === item.id);
    if (!isExist) {
      const updatedCart = [...cartItems, item];
      // 更新全局状态
      dispatch({
        type: actionType.SET_CARTITEMS,
        cartItems: updatedCart,
      });
      // 同步到本地存储
      localStorage.setItem("cartItems", JSON.stringify(updatedCart));
    }
  };

  useEffect(() => {
    rowContainer.current.scrollLeft += scrollValue;
  }, [scrollValue]);

  // 组件返回部分修改点击事件
  return (
    // ...原JSX结构
    <motion.div
      whileTap={{ scale: 0.75 }}
      className="w-8 h-8 rounded-md bg-orange-500 hover:bg-orange-600 "
      onClick={() => handleAddToCart(item)}
    >
      <MdShoppingBasket className="text-white text-2xl m-1" />
    </motion.div>
    // ...原JSX结构
  );
};
  1. Firebase数据同步补充
    如果需要从Firebase同步用户云端购物车,要在组件挂载时先保留本地数据,再合并云端数据,避免覆盖:
// 示例:在购物车页面或全局状态中同步Firebase数据
useEffect(() => {
  const syncFirebaseCart = async () => {
    const currentUser = /* 获取当前登录用户 */;
    if (currentUser) {
      const cartDoc = await firebase.firestore().collection('carts').doc(currentUser.uid).get();
      if (cartDoc.exists) {
        const cloudCart = cartDoc.data().items;
        // 合并本地与云端数据,优先保留本地新增商品
        const mergedCart = [...new Map([...cartItems, ...cloudCart].map(item => [item.id, item])).values()];
        dispatch({
          type: actionType.SET_CARTITEMS,
          cartItems: mergedCart,
        });
        localStorage.setItem("cartItems", JSON.stringify(mergedCart));
      }
    }
  };
  syncFirebaseCart();
}, []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:01:26