Первый принцип документации Redux:
Состояние всего вашего приложения хранится в дереве объектов в одном хранилище.
И мне действительно казалось, что я хорошо понимаю всех руководителей. Но теперь я не понимаю, что означает приложение.
Я понимаю, если приложение означает лишь одну из небольших сложных частей на сайте и работает только на одной странице. Но что, если приложение означает весь сайт? Должен ли я использовать LocalStorage или cookie или что-то еще для сохранения дерева состояний? но что, если браузер не поддерживает LocalStorage?
Я хочу знать, как разработчики хранят свое дерево состояний! :)
Ответы:
Если вы хотите сохранить свое состояние redux при обновлении браузера, лучше всего сделать это с помощью промежуточного программного обеспечения redux. Ознакомьтесь с промежуточным программным обеспечением redux-persist и redux-storage . Они оба пытаются выполнить одну и ту же задачу по сохранению вашего состояния redux, чтобы его можно было сохранять и загружать по желанию.
-
редактировать
Прошло некоторое время с тех пор, как я вернулся к этому вопросу, но, увидев, что другой (хотя и более одобренный ответ) поощряет развертывание вашего собственного решения, я решил, что отвечу на это еще раз.
На момент редактирования обе библиотеки были обновлены в течение последних шести месяцев. Моя команда уже несколько лет использует redux-persist в продакшене и не имеет никаких проблем.
Хотя это может показаться простой проблемой, вы быстро обнаружите, что развертывание собственного решения не только вызовет бремя обслуживания, но и приведет к ошибкам и проблемам с производительностью. Первые примеры, которые приходят на ум:
JSON.stringify
иJSON.parse
может не только снизить производительность, когда он не нужен, но и вызвать ошибки, которые, если их не обработать в критически важном фрагменте кода, таком как ваше хранилище redux, могут привести к сбою вашего приложения.Подводя итог, для 3kB minified + gzip (на момент редактирования) это не проблема, я бы попросил мою команду решить саму себя.
источник
Редактировать 25 августа 2019 г.
Как сказано в одном из комментариев. Исходный пакет redux-storage перемещен в response-stack . Этот подход по-прежнему ориентирован на реализацию вашего собственного решения для управления состоянием.
Оригинальный ответ
Хотя предоставленный ответ был действителен в какой-то момент, важно отметить, что исходный пакет redux-storage устарел и больше не поддерживается ...
Теперь, если вы не хотите иметь зависимости от других пакетов, чтобы избежать подобных проблем в будущем, очень легко развернуть собственное решение.
Все, что вам нужно сделать, это:
1- Создайте функцию, которая возвращает состояние из,
localStorage
а затем передает состояниеcreateStore
функции redux во втором параметре, чтобы гидратировать хранилищеconst store = createStore(appReducers, state);
2- Слушайте изменения состояния и каждый раз, когда состояние изменяется, сохраняйте состояние в
localStorage
store.subscribe(() => { //this is just a function that saves state to localStorage saveState(store.getState()); });
И все ... Я действительно использую что-то подобное в производстве, но вместо использования функций я написал очень простой класс, как показано ниже ...
class StateLoader { loadState() { try { let serializedState = localStorage.getItem("http://contoso.com:state"); if (serializedState === null) { return this.initializeState(); } return JSON.parse(serializedState); } catch (err) { return this.initializeState(); } } saveState(state) { try { let serializedState = JSON.stringify(state); localStorage.setItem("http://contoso.com:state", serializedState); } catch (err) { } } initializeState() { return { //state object } }; } }
а затем при загрузке вашего приложения ...
import StateLoader from "./state.loader" const stateLoader = new StateLoader(); let store = createStore(appReducers, stateLoader.loadState()); store.subscribe(() => { stateLoader.saveState(store.getState()); });
Надеюсь, это кому-то поможет
Примечание производительности
Если изменения состояния в вашем приложении происходят очень часто, слишком частое сохранение в локальное хранилище может снизить производительность вашего приложения, особенно если граф объекта состояния для сериализации / десериализации большой. В этих случаях вы можете захотеть дребезг или задушить функцию , которая сохраняет состояние в LocalStorage использование
RxJs
,lodash
или что - то подобное.источник
Это основано на ответе Лео (который должен быть принятым ответом, поскольку он достигает цели вопроса без использования каких-либо сторонних библиотек).
Я создал класс Singleton, который создает хранилище Redux, сохраняет его с использованием локального хранилища и обеспечивает простой доступ к его хранилищу через геттер .
Чтобы использовать его, просто поместите следующий элемент Redux-Provider вокруг основного класса:
// ... Your other imports import PersistedStore from "./PersistedStore"; ReactDOM.render( <Provider store={PersistedStore.getDefaultStore().store}> <MainClass /> </Provider>, document.getElementById('root') );
и добавьте в свой проект следующий класс:
import { createStore } from "redux"; import rootReducer from './RootReducer' const LOCAL_STORAGE_NAME = "localData"; class PersistedStore { // Singleton property static DefaultStore = null; // Accessor to the default instance of this class static getDefaultStore() { if (PersistedStore.DefaultStore === null) { PersistedStore.DefaultStore = new PersistedStore(); } return PersistedStore.DefaultStore; } // Redux store _store = null; // When class instance is used, initialize the store constructor() { this.initStore() } // Initialization of Redux Store initStore() { this._store = createStore(rootReducer, PersistedStore.loadState()); this._store.subscribe(() => { PersistedStore.saveState(this._store.getState()); }); } // Getter to access the Redux store get store() { return this._store; } // Loading persisted state from localStorage, no need to access // this method from the outside static loadState() { try { let serializedState = localStorage.getItem(LOCAL_STORAGE_NAME); if (serializedState === null) { return PersistedStore.initialState(); } return JSON.parse(serializedState); } catch (err) { return PersistedStore.initialState(); } } // Saving persisted state to localStorage every time something // changes in the Redux Store (This happens because of the subscribe() // in the initStore-method). No need to access this method from the outside static saveState(state) { try { let serializedState = JSON.stringify(state); localStorage.setItem(LOCAL_STORAGE_NAME, serializedState); } catch (err) {} } // Return whatever you want your initial state to be static initialState() { return {}; } } export default PersistedStore;
источник