Как сохранить состояние в localStorage с помощью инструментария redux в проекте nextjs

avatar
Raju Ahammad
9 августа 2021 в 06:08
1259
3
0

Я хочу сохранить свое обновленное состояние в localStorage, но при попытке сделать это возникает ошибка. 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))
}

Как это решить?

Источник
Drew Reese
9 августа 2021 в 06:19
0

И в чем ошибка? Пытаетесь проанализировать нулевое/неопределенное состояние корзины из localStorage здесь JSON.parse(localStorage.getItem('cart'));?

Raju Ahammad
9 августа 2021 в 06:40
0

Ошибка @DrewReese: localstorage is not defined

Drew Reese
9 августа 2021 в 06:49
0

О, я вижу, вы упоминаете Nextjs в заголовке, да, я не думаю, что localStorage доступен в SSR. Я не уверен в лучшем решении здесь, но я подозреваю, что оно будет включать инициализацию некоторого состояния на стороне клиента, когда компонент где-то монтируется.

Elias
9 августа 2021 в 07:00
0

Я предполагаю, что вам нужно либо отключить рендеринг на стороне сервера, либо убедиться, что код выполняется только на клиенте.

Elias
9 августа 2021 в 07:02
0

addToCartAction должно быть в порядке, это выполняется только при нажатии кнопки (я полагаю). Проблема заключается в createSlice, который выполняется при импорте, на сервере и на клиенте.

Raju Ahammad
9 августа 2021 в 08:29
0

@Elias, с Context API мы использовали хук useEffect, но я не нашел ни одного примера с набором инструментов Redux. prnt.sc/1lkzb0x

Elias
9 августа 2021 в 08:58
0

@RajuAhammad да, эффект использования выполняется только на клиенте, так что проблема в этом.

Ответы (3)

avatar
Shariar
3 ноября 2021 в 02:47
2

Решение:

const data = typeof window !== "undefined" && localStorage.getItem("cart") ? 
 JSON.parse(localStorage.getItem("cart")) : []
Trí Phan
3 ноября 2021 в 03:29
0

Спасибо за ответ, но было бы лучше, если бы вы добавили некоторые пояснения.

avatar
phry
9 августа 2021 в 08:37
1

Вообще, уже было много сказано о том, что это не работает в SSR. Однако независимо от этого: у вас не должно быть побочных эффектов в ваших редукционных редукторах, и это один из таких побочных эффектов. Просто так нельзя.

Вместо этого либо напишите свою собственную реализацию, используя store.subscribe, либо используйте redux-persist. Поскольку последняя является библиотекой, которая уже задокументирована, я, вероятно, выберу последнюю. Однако в обоих случаях перед выполнением чего-либо, касающегося localStorage, вам всегда нужно проверять, находитесь ли вы на клиенте, а не на сервере, поэтому оберните его в блок if и проверьте, является ли window.localStorage undefined, прежде чем вызывать его. (или инициализация redux-persist).

avatar
Ayush Gupta
9 августа 2021 в 07:10
0

Вместо этого вы можете использовать файлы cookie. Другим решением будет использование node-localstorage

var LocalStorage = require('node-localstorage').LocalStorage,
localStorage = new LocalStorage('./storage')
Elias
9 августа 2021 в 09:01
0

node-localstorage на самом деле бесполезен (вероятно, наоборот), потому что у каждого пользователя будет то же самое.