Как сохранить состояние Redux в локальном хранилище без какой-либо внешней библиотеки?
Redux согласно официальной документации - это контейнер с предсказуемым состоянием для приложений JavaScript. Проще говоря, это библиотека управления состоянием, с помощью Redux управление состоянием компонентов становится очень простым. Мы можем управлять состоянием приложения, создавая глобальное состояние, известное как хранилище.
Идея использования Redux может быть хорошей для приложения со сложной реакцией, но это состояние не сохраняется на всем протяжении. Это означает, что после перезагрузки браузера состояние приложения изменяется и достигает состояния по умолчанию. Сохранять данные таких реагирующих приложений очень просто. Мы будем использовать локальное хранилище для хранения текущего состояния приложения React и сохранения данных даже при перезагрузках.
Создание приложения React и установка модуля:
Шаг 1. Создайте приложение React, используя следующую команду:
npx создать-реагировать-приложение myapp
Шаг 2: После создания папки проекта, то есть myapp, перейдите к ней с помощью следующей команды:
cd myapp
Шаг 3: После создания приложения ReactJS установите необходимые модули, используя следующую команду:
npm установить redux npm установить React-redux
Структура проекта: это будет выглядеть следующим образом.
Пример: мы создадим простое приложение корзины покупок, с помощью которого мы будем сохранять данные в нашем локальном хранилище.
Имя файла - App.js Это компонент нашего приложения React. Импортируются все зависимости, которые требуются для типичного приложения React. Функция провайдера импортируется из react-redux. Это будет действовать как компонент оболочки для нашего приложения, этому компоненту упаковки мы передадим хранилище. Магазин - это в основном глобальное состояние нашего приложения.
Javascript
import React from "react" ; import { Provider } from 'react-redux' ; import CartContainer from "./components/CartContainer" ; // Store import { store } from './store' ; import { saveState } from './localStorage' ; store.subscribe(() => { saveState({ cart: store.getState().cart, total: store.getState().total, amount: store.getState().amount }); }); // Items const cartItems = [ { id: 1, title: "Samsung" , price: 799.99, img: "shorturl.at/ajkq9" , amount: 1 }, { id: 2, title: "Google pixel Max" , price: 399.99, img: "shorturl.at/ajkq9" , amount: 1 }, { id: 3, title: "Xiaomi" , price: 999.99, img: "shorturl.at/ajkq9" , amount: 1 } ]; function App() { return ( <Provider store={store}> <CartContainer cart={cartItems} /> </Provider> ); } export App; default |
Filename- store.js В этом файле базовая настройка магазина выполняется с помощью redux. Хранилище инициализируется, и состояние сохраняется в локальном хранилище. Магазин redux содержит итоги, количество и элементы корзины. Состояние этого магазина будет позже сохранено в локальном хранилище.
Javascript
import reducer from './reducer' ; import { createStore } from 'redux' ; import { loadState } from './localStorage' ; const cartItems = [ { id: 1, title: "Samsung" , price: 799.99, img: "shorturl.at/ajkq9" , amount: 1 }, { id: 2, title: "Google pixel Max" , price: 399.99, img: "shorturl.at/ajkq9" , amount: 1 }, { id: 3, title: "Xiaomi" , price: 999.99, img: "shorturl.at/ajkq9" , amount: 1 } ]; const persistedState = loadState(); const initialStore = { cart: cartItems, amount: 0, total: 0, persistedState } export const store = createStore(reducer, persistedState); |
Имя файла: reducer.js Этот файл содержит функцию редуктора. В соответствии с действием, отправленным через пользовательский интерфейс, выполняются соответствующие функции. В основном наш редуктор будет иметь дело с 5 основными операциями нашего приложения, а именно:
- Действие УМЕНЬШИТЬ уменьшает количество товаров в нашей корзине.
- Действие УВЕЛИЧИТЬ увеличивает количество товаров в нашей корзине.
- Действие УДАЛИТЬ удаляет товар из корзины.
- Действие CLEAR_CART в основном очищает всю корзину.
- Действие GET_TOTALS получает сумму всех товаров в нашей корзине.
Примечание. Следует помнить одну важную вещь: не изменяйте состояние приложения при использовании Redux.
Javascript
import { INCREASE, DECREASE, REMOVE, CLEAR_CART, GET_TOTALS, } from './actions' ; function reducer(state, action) { if (action.type === DECREASE) { return { ...state, cart: state.cart.map((item) => { if (item.id === action.payload.id) { if (item.amount === 0) { return item; } else { item.amount--; } } return item; }) } } if (action.type === INCREASE) { return { ...state, cart: state.cart.map((item) => { if (item.id === action.payload.id) { item.amount++; } return item; }) } } if (action.type === CLEAR_CART) { return { ...state, cart: [] }; } if (action.type === REMOVE) { return {...state, cart: state.cart.filter(item => item.id !== action.payload.id)} } if (action.type === GET_TOTALS) { let { total, amount } = state.cart.reduce((cartTotal, cartItem) => { const { price, amount } = cartItem; cartTotal.amount += amount; cartTotal.total += Math.floor(amount * price); return cartTotal; }, { amount: 0, total: 0 }); return { ...state, total, amount }; } return state; } reducer; export default |
Имя файла: CartItem.js Этот файл содержит код для компонента cartItem
Именно в этом файле отправляются разные методы. Функция mapDispatchToProps включает три действия mapDispatchToProps
Javascript
import React from "react" ; import { connect } from 'react-redux' ; import { DECREASE, INCREASE, REMOVE } from '../actions' ; const CartItem = ({ title, price, img, amount, increase, decrease, remove }) => { return ( <div className= "cart-item" > <img src={img} alt={img} /> <div> <h4>{title}</h4> <h4 className= "item-price" >${price}</h4> </div> <div> { /* increase amount */ } <button className= "amount-btn" onClick={() => increase()}> <path d= "M10.707 7.05L10 6.343 4.343 12l1.414 1.414L10 9.172l4.243 4.242L15.657 12z" /> </svg> </button> { /* amount */ } <p className= "amount" >{amount}</p> { /* decrease amount */ } <button className= "amount-btn" onClick={() => decrease()} > <path d= "M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" /> </svg> </button> </div> </div> ); }; const mapDispatchToProps = (dispatch, ownProps) => { const { id, amount } = ownProps; return { increase: () => dispatch({ type: INCREASE, payload: { id } }), decrease: () => dispatch({ type: DECREASE, payload: { id } }), remove: () => dispatch({ type: REMOVE, payload: { id, amount } }) } } export connect( default null , mapDispatchToProps)(CartItem); |
Имя файла - CartContainer.js Этот файл импортирует компонент carttem и передает им необходимые реквизиты. Здесь мы подключаем mapStateToProps
и mapDispatchToProps
а затем передаем ему CartContainer.
Javascript
import React from "react" ; import CartItem from './CartItem' ; import { connect } from 'react-redux' ; import { CLEAR_CART, GET_TOTALS } from '../actions' ; const CartContainer = ({ cart = [], total, remove, getTotal }) => { React.useEffect(() => { getTotal(); }) if (cart.length === 0) { return ( <section className= "cart" > <header> <h2>your bag</h2> <h4 className= "empty-cart" > is currently empty </h4> </header> </section> ); } return ( <section className= "cart" > { /* cart header */ } <header> <h2>your bag</h2> </header> { /* cart items */ } <article> {cart.map((item) => { return <CartItem key={item.id} {...item} /> })} </article> { /* cart footer */ } <footer> <hr /> <div className= "cart-total" > <h4> total <span>${total}</span> </h4> </div> <button className= "btn clear-btn" onClick={() => remove()} >clear cart</button> </footer> </section> ); }; function mapStateToProps(store) { const { cart, total } = store; return { cart: cart, total: total }; } function mapDispatchToProps(dispatch) { return { remove: () => dispatch({ type: CLEAR_CART }), getTotal: () => dispatch({ type: GET_TOTALS }) } } export default connect(mapStateToProps, mapDispatchToProps)(CartContainer); |
Имя файла- localStorage.js Теперь мы добавим файл localStorage.js. Метод сохранения данных требует всего четырех простых шагов:
Шаг 1. Создайте файл с именем localStorage.js в корневой папке, обычно в папке src вашего приложения React. В этом файле мы добавим два метода: один для загрузки состояния из локального хранилища, а второй - для сохранения состояния в локальное хранилище. Код для метода loadState выглядит следующим образом:
Javascript
export const loadState = () => { try { const serialState = localStorage.getItem( 'appState' ); if (serialState === null ) { return undefined; } return JSON.parse(serialState); } catch (err) { return undefined; } }; |
В локальном хранилище данные хранятся в виде пар ключ-значение. Здесь ключом является appState, а значением будет фактическое состояние приложения.
Шаг 2: Код для saveState
выглядит следующим образом:
Javascript
export const saveState = (state) => { try { const serialState = JSON.stringify(state); localStorage.setItem( 'appState' , serialState); } catch (err) { console.log(err); } }; |
Шаг 3. Теперь в файле store.js импортируйте метод loadState
из файла localStorage.js и получите его значение в константе persistedState
Теперь в качестве объекта поместите эту persistedState
с фактическим состоянием вашего приложения и экспортируйте ее, передав ее в хранилище.
Имя файла- store.js
Javascript
import reducer from './reducer' ; import {createStore} from 'redux' ; import {loadState} from './localStorage' ; const persistedState = loadState(); const initialStore={ /* state of your app */ cart:cartItems, amount:0, total:0, persistedState } export const store=createStore(reducer,persistedState); |
Шаг 4: Это самый важный шаг, поскольку он включает в себя сохранение состояния в локальном хранилище браузера. Теперь в компоненте импорта App.js магазин из файла store.js и метод saveState () из файла localStorage.js. Теперь сохраните состояние приложения, вызвав функцию подписки из магазина.
Имя файла - App.js
Javascript
import {store} from './store' ; import {saveState} from './localStorage' ; store.subscribe(() => { saveState({ /* example state */ cart:store.getState().cart, total:store.getState().total, amount: store.getState().amount }); }); |
Теперь просто передайте это хранилище компоненту Provider в компоненте App, и данные станут постоянными в локальном хранилище.
Вывод: вы можете проверить состояние, открыв инструменты разработчика в Chrome, а затем перейдя в приложение, затем в хранилище, а затем в локальное хранилище. В локальном хранилище вы увидите ключ с именем appState . Это место, где хранятся все данные.