LocalStorage для корзины товаров (React/Redux)
Стоит задача, чтобы после перезагрузки данные корзины покупок оставались. Я пытаюсь это прикрутить через LocalStoge и Redux. Прошу помочь. Я совсем не понимаю иду ли я в правильном направлении. В коде выделил все, что касается этой проблемы.
Мои попытки:
reducer
case 'SET_LOCAL_STORE': {
const oldItems = {
...state.items,
};
return {
...state,
items: oldItems,
}
}
///////////////////////////////////////
default:
return state;
action:
export const setLocalStorage = (itemsObj) => ({
type: 'MINUS_DELETE_ITEM',
payload: itemsObj,
})
Компонент Cart :
[JS]import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Link } from 'react-router-dom';
import cartEmptyImage from '../assets/img/empty-cart.png';
import { CartItem, Button, SubmitForm } from '../components';
import { clearCart, removeCartItem, plusCartItem, minusCartItem, minusDeleteCartItem,
setLocalStorage} from '../redux/actions/cart';
function Cart() {
const dispatch = useDispatch();
const { totalPrice, totalCount, items } = useSelector(({ cart }) => cart);
const addedDetectors = Object.keys(items).map((key) => {
return items[key].items[0];
});
```
/* В компоненте Cart пробую при загрузке записать данные в LocalStorage*/
React.useEffect(() => {
dispatch(setLocalStorage(window.localStorage.setItem('some-key', JSON.stringify(items)))); // items
елементы корзины
}, []);
```
/////////////////////////////////////////////////////
const onClearCart = () => {
if (window.confirm('Вы действительно хотите очистить корзину?')) {
dispatch(clearCart());
}
};
const onRemoveItem = (id) => {
if (window.confirm('Вы действительно хотите удалить?')) {
dispatch(removeCartItem(id));
}
};
Полностью Reducer cart
const initialState = {
items: {},
totalPrice: '',
totalCount: '',
};
const getTotalPrice = (arr) => arr.reduce((sum, obj) => obj.price + sum, 0);
const _get = (obj, path) => {
const [firstKey, ...keys] = path.split('.');
return keys.reduce((val, key) => {
return val[key];
}, obj[firstKey]);
};
const getTotalSum = (obj, path) => {
return Object.values(obj).reduce((sum, obj) => {
const value = _get(obj, path);
return sum + value;
}, 0);
};
const cart = (state = initialState, action) => {
switch (action.type) {
case 'ADD_DETECTOR_CART': {
const currentDetectorItems = !state.items[action.payload.id]
? [action.payload]
: [...state.items[action.payload.id].items, action.payload];
const newItems = {
...state.items,
[action.payload.id]: {
items: currentDetectorItems,
totalPrice: getTotalPrice(currentDetectorItems,),
},
};
const totalCount = getTotalSum(newItems, 'items.length');
const totalPrice = getTotalSum(newItems, 'totalPrice');
return {
...state,
items: newItems,
totalCount,
totalPrice,
};
}
case 'REMOVE_CART_ITEM': {
const newItems = {
...state.items,
};
const currentTotalPrice = newItems[action.payload].totalPrice;
const currentTotalCount = newItems[action.payload].items.length;
delete newItems[action.payload];
return {
...state,
items: newItems,
totalPrice: state.totalPrice - currentTotalPrice,
totalCount: state.totalCount - currentTotalCount,
};
}
case 'PLUS_CART_ITEM': {
const newObjItems = [
...state.items[action.payload].items,
state.items[action.payload].items[0],
];
const newItems = {
...state.items,
[action.payload]: {
items: newObjItems,
totalPrice: getTotalPrice(newObjItems),
},
};
const totalCount = getTotalSum(newItems, 'items.length');
const totalPrice = getTotalSum(newItems, 'totalPrice');
return {
...state,
items: newItems,
totalCount,
totalPrice,
};
}
case 'MINUS_CART_ITEM': {
const oldItems = state.items[action.payload].items;
const newObjItems = oldItems.length > 1 ? state.items[action.payload].items.slice(1) : oldItems;
const newItems = {
...state.items,
[action.payload]: {
items: newObjItems,
totalPrice: getTotalPrice(newObjItems),
},
};
const totalCount = getTotalSum(newItems, 'items.length');
const totalPrice = getTotalSum(newItems, 'totalPrice');
return {
...state,
items: newItems,
totalCount,
totalPrice,
};
}
case 'CLEAR_CART':
return { totalPrice: 0, totalCount: 0, items: {} };
///// Мои попытки ////////////////////
case 'SET_LOCAL_STORE': {
const oldItems = {
...state.items,
};
return {
...state,
items: oldItems,
}
}
///////////////////////////////////////
default:
return state;
}
};
Ответы (1 шт):
В вашей ситуации лучше всего подключить redux persist. Настройка его займет мало времени. Почему у вас action имеет такой тип:
type: 'MINUS_DELETE_ITEM',
Но его нет в редьюсере.
Работа с индексами плохая практика:
.items[0]
Почему при загрузке, а не при размонтировании пытаетесь записать. Вы ведь будете работать с корзиной и есть вероятность, что координально изменятся. Т.е. выходит, что записывать нужно не в этот момент;