Stack Exchange
How to save state in localStorage using redux toolkit on nextjs project
I want to save my updated state to localStorage but when try this facing an error. localstorage is not defined
cartSlice.jsx
import {v4 as uuid} from "uuid";
import {createSlice} from "@reduxjs/toolkit";
const data = JSON.parse(localStorage.getItem('cart'));
export const cartSlice = createSlice({
  name: 'shoppingCart',
  initialState: data ? data : [],
  reducers: {
    addToCart: (state, action) => {
        const product = action.payload;
        const productInCart = state.find(item => item.id === product.id && item.color === product.color && item.size === product.size && item.material === product.material);

        if (productInCart) {
            const cartProductIndex = state.findIndex(item => item.id === product.id);
            state[cartProductIndex].quantity = state[cartProductIndex].quantity + product.quantity;
        } else {
            product['cartId'] = uuid();
            return [product, ...state];
        }

        localStorage.setItem('cart', JSON.stringify(state));
    }
}
})

cartAction.js
import {addToCart} from "@slices/cartSlice";

export const addToCartAction = (payload) => (dispatch) => {
 dispatch(addToCart(payload))
}

How to solve this?

And what is the error? Trying to parse null/undefined cart state from localStorage here JSON.parse(localStorage.getItem('cart'));?

@DrewReese error is localstorage is not defined

Oh, I see you mention Nextjs in the title, yeah, I don't think localStorage is available in SSR. I am uncertain of the best solution here, but I suspect it'll involve initializing some state on the client side when a component mounts somewhere.

I assume you either have to disable server-side rendering or ensure that the code is only executed on the client.

addToCartAction should be fine, that is only executed upon a button press (I assume). The issue is the createSlice which is executed on import, on the server and on the client.

@Elias, With Context API we did with useEffect hook but I don't find any example with Redux toolkit.
https://prnt.sc/1lkzb0x

@RajuAhammad yes use effect is only executed on the client so that would be the issue

The solution is


const data = typeof window !== "undefined" && localStorage.getItem("cart") ? 
 JSON.parse(localStorage.getItem("cart")) : []




Thank you for the answer but it could be better if you add some explanations.

Generally, there was already a lot of stuff said regarding to this not working in SSR.
Independently of that though: You must not have side effects in your redux reducers, and this is one such side effect. It's just not allowed like that.
Instead, either write your own implementation using store.subscribe or use redux-persist. As the latter is a library that is already documented, I would probably go for the latter. In both cases though, before executing anything regarding localStorage, you always have to check if you are on the client and not on the server, so wrap it into a if block and check if window.localStorage is undefined before calling it (or initializing redux-persist).

You can use Cookies instead. The other solution will be to use node-localstorage
var LocalStorage = require('node-localstorage').LocalStorage,
localStorage = new LocalStorage('./storage')


node-localstorage would not really be of use (probably the opposite) because every user would have the same.
