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

Next.js 13 App Router中Redux切片使用localStorage失效求助

解决Next.js 13 App Router中Redux结合localStorage崩溃的问题

问题根源

你的代码在Redux切片的initialState中直接调用localStorage.getItem(),但Next.js 13 App Router默认以服务器组件渲染,服务器环境不存在localStorage对象,初始化时会抛出错误导致应用崩溃。即便给组件加了'use client',只要切片文件被服务器端代码(比如全局Store配置文件)引入,就会触发这个错误。

正确实现方案

步骤1:修改Redux切片的初始状态

把initialState中的cartItems改为默认空数组,避免在服务器端访问localStorage:

import { createSlice } from "@reduxjs/toolkit";
import toast from "react-hot-toast";

const initialState = {
  cartState: false,
  cartItems: [], // 服务器端初始为空
  cartTotalAmount: 0,
  cartTotalQantity: 0,
};

// 其余reducer代码保持不变

步骤2:添加加载localStorage数据的Action

在切片的reducers里新增setLoadCartFromLocalStorage Action,用于从localStorage读取数据并更新状态:

const CartSlice = createSlice({
  initialState,
  name: "cart",
  reducers: {
    // 保留原有所有reducer
    setLoadCartFromLocalStorage: (state) => {
      const savedCart = localStorage.getItem("cart");
      if (savedCart) {
        state.cartItems = JSON.parse(savedCart);
        // 加载后重新计算总价和数量
        const { totalAmount, totalQTY } = state.cartItems.reduce((cartTotal, cartItem)=> {
          const { price, cartQuantity } = cartItem;
          const totalPrice = price * cartQuantity;
          cartTotal.totalAmount += totalPrice;
          cartTotal.totalQTY += cartQuantity;
          return cartTotal;
        }, { totalAmount: 0, totalQTY: 0 });
        state.cartTotalAmount = totalAmount;
        state.cartTotalQantity = totalQTY;
      }
    },
  },
});

// 导出新增的Action
export const {
  // 保留原有导出的Action
  setLoadCartFromLocalStorage
} = CartSlice.actions;

步骤3:在客户端组件中触发加载操作

找一个全局的客户端组件(比如layout.tsx,记得加'use client'),在组件挂载时dispatch这个加载Action:

'use client';
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { setLoadCartFromLocalStorage } from '@/features/cart/CartSlice';

export default function RootLayout({ children }) {
  const dispatch = useDispatch();

  useEffect(() => {
    // 组件挂载时加载本地存储的购物车数据
    dispatch(setLoadCartFromLocalStorage());
  }, [dispatch]);

  return (
    <html lang="zh-CN">
      <body>{children}</body>
    </html>
  );
}

步骤4:保留原有localStorage写入逻辑

你原来在各个reducer中调用localStorage.setItem("cart", JSON.stringify(state.cartItems))的逻辑可以保留,这部分只会在客户端执行(只有客户端组件会dispatch这些Action),不会触发服务器端错误。

额外优化建议

  • 把计算总价的逻辑封装成单独函数,避免在setLoadCartFromLocalStorage和setGetTotals中重复代码。
  • 确保Redux Store配置文件是客户端组件,或遵循Next.js官方推荐的Redux集成方式,在客户端组件中创建Store并通过Provider包裹应用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 04:44:55