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

NextJS中刷新时localStorage购物车数据被重置为空的解决方法

解决Next.js购物车localStorage刷新重置及SSR报错问题

问题根源

  1. SSR报错原因:Next.js在服务器端渲染阶段不存在window和localStorage对象,若直接在组件顶层或useState初始化时调用localStorage,会触发localStorage is not defined错误。
  2. 刷新后重置原因:组件挂载时,cartItems初始值为空数组,触发依赖该状态的第二个useEffect,将空数组写入localStorage覆盖原有数据;随后第一个useEffect读取到的已是空值,导致购物车被重置。

修复方案

方案一:调整useEffect执行逻辑,避免初始空值覆盖

通过控制localStorage写入时机,确保仅在有效数据更新时同步存储,同时在客户端初始化时正确读取历史数据:

import { useState, useEffect, createContext } from 'react';

export const CartContext = createContext();

export function CartProvider({ children }) {
  // 初始state设为null,避免空数组触发不必要的存储
  const [cartItems, setCartItems] = useState(null);

  // 客户端初始化:读取localStorage中的购物车数据
  useEffect(() => {
    if (typeof window !== 'undefined') {
      try {
        const storedCartItems = localStorage.getItem('cartItems');
        // 解析数据,确保返回数组格式
        setCartItems(storedCartItems ? JSON.parse(storedCartItems) : []);
      } catch (err) {
        console.error('购物车数据解析失败', err);
        setCartItems([]);
      }
    }
  }, []);

  // 仅当cartItems完成初始化后,才同步到localStorage
  useEffect(() => {
    if (cartItems !== null && typeof window !== 'undefined') {
      localStorage.setItem('cartItems', JSON.stringify(cartItems));
    }
  }, [cartItems]);

  // 等待state初始化完成,避免子组件拿到null值
  if (cartItems === null) {
    return null; // 可替换为自定义加载组件
  }

  // 购物车操作示例:添加商品
  const addToCart = (item) => {
    setCartItems(prev => [...prev, item]);
  };

  return (
    <CartContext.Provider value={{ cartItems, addToCart }}>
      {children}
    </CartContext.Provider>
  );
}

方案二:使用useState工厂函数(Next.js 13+ App Router适配)

在App Router中,需先标记组件为客户端组件(添加'use client'指令),再通过useState工厂函数在客户端初始化状态:

'use client';
import { useState, useEffect, createContext } from 'react';

export const CartContext = createContext();

export function CartProvider({ children }) {
  // 工厂函数初始化:仅在客户端执行,避免SSR报错
  const [cartItems, setCartItems] = useState(() => {
    if (typeof window !== 'undefined') {
      try {
        const stored = localStorage.getItem('cartItems');
        return stored ? JSON.parse(stored) : [];
      } catch (err) {
        console.error('购物车数据解析失败', err);
        return [];
      }
    }
    return []; // 服务器端返回空数组,客户端会自动覆盖
  });

  // 同步购物车数据到localStorage
  useEffect(() => {
    if (typeof window !== 'undefined') {
      localStorage.setItem('cartItems', JSON.stringify(cartItems));
    }
  }, [cartItems]);

  const addToCart = (item) => {
    setCartItems(prev => [...prev, item]);
  };

  return (
    <CartContext.Provider value={{ cartItems, addToCart }}>
      {children}
    </CartContext.Provider>
  );
}

核心注意事项

  • 客户端组件标记:App Router中使用localStorage的组件必须添加'use client'指令,否则会在服务器端执行时报错。
  • 数据格式校验:解析localStorage数据时添加try-catch,避免非法JSON格式导致的崩溃,同时确保返回值为数组类型。
  • 初始化顺序:确保先读取历史数据再执行存储操作,避免初始空值覆盖原有数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 15:48:04