El primer principio de la documentación de Redux es:
El estado de toda su aplicación se almacena en un árbol de objetos dentro de una sola tienda.
Y de hecho pensé que comprendo bien todos los principios. Pero ahora estoy confundido sobre qué significa la aplicación.
Si la aplicación significa solo una parte poco complicada en el sitio web y funciona en una sola página, lo entiendo. Pero, ¿y si aplicación significa sitio web completo? ¿Debo usar LocalStorage o cookie o algo para mantener el árbol del estado? pero ¿qué pasa si el navegador no es compatible con LocalStorage?
¡Quiero saber cómo los desarrolladores mantienen su árbol de estado! :)
Respuestas:
Si desea mantener su estado redux a través de una actualización del navegador, es mejor hacerlo usando el middleware redux. Echa un vistazo a la redux-persistir y redux de almacenamiento intermedio. Ambos intentan realizar la misma tarea de almacenar su estado redux para que pueda guardarse y cargarse a voluntad.
-
Editar
Ha pasado algún tiempo desde que revisé esta pregunta, pero al ver que la otra (aunque la respuesta más votada a favor) alienta a lanzar su propia solución, pensé que respondería esto nuevamente.
A partir de esta edición, ambas bibliotecas se han actualizado en los últimos seis meses. Mi equipo ha estado usando redux-persist en producción durante algunos años y no ha tenido problemas.
Si bien puede parecer un problema simple, rápidamente descubrirá que implementar su propia solución no solo causará una carga de mantenimiento, sino que también generará errores y problemas de rendimiento. Los primeros ejemplos que me vienen a la mente son:
JSON.stringify
yJSON.parse
no solo puede dañar el rendimiento cuando no es necesario, sino también generar errores que, cuando no se manejan en una parte crítica del código, como su tienda redux, pueden bloquear su aplicación.En resumen, para 3kB minificado + gzip (en el momento de esta edición) esto no es un problema, le pediría a mi equipo que lo resuelva solo.
fuente
Editar 25-ago-2019
Como se indica en uno de los comentarios. El paquete original de redux-storage se ha movido a react-stack . Este enfoque aún se enfoca en implementar su propia solución de administración de estado.
Respuesta original
Si bien la respuesta proporcionada fue válida en algún momento, es importante notar que el paquete original redux-storage ha quedado obsoleto y ya no se mantiene ...
Ahora bien, si no desea tener dependencias en otros paquetes para evitar problemas como estos en el futuro, es muy fácil lanzar su propia solución.
Todo lo que necesitas hacer es:
1- Cree una función que devuelva el estado desde
localStorage
y luego pase el estado a la funcióncreateStore
's redux en el segundo parámetro para hidratar la tiendaconst store = createStore(appReducers, state);
2- Escuche los cambios de estado y cada vez que cambie el estado, guarde el estado para
localStorage
store.subscribe(() => { //this is just a function that saves state to localStorage saveState(store.getState()); });
Y eso es todo ... De hecho, uso algo similar en producción, pero en lugar de usar funciones, escribí una clase muy simple como la siguiente ...
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 } }; } }
y luego al arrancar su aplicación ...
import StateLoader from "./state.loader" const stateLoader = new StateLoader(); let store = createStore(appReducers, stateLoader.loadState()); store.subscribe(() => { stateLoader.saveState(store.getState()); });
Espero que ayude a alguien
Nota de rendimiento
Si los cambios de estado son muy frecuentes en su aplicación, guardar en el almacenamiento local con demasiada frecuencia podría dañar el rendimiento de su aplicación, especialmente si el gráfico de objetos de estado para serializar / deserializar es grande. Para estos casos, es posible que desee eliminar el rebote o acelerar la función que guarda el estado en localStorage usando
RxJs
,lodash
o algo similar.fuente
Esto se basa en la respuesta de Leo (que debería ser la respuesta aceptada, ya que logra el propósito de la pregunta sin usar bibliotecas de terceros).
Creé una clase Singleton que crea una tienda Redux, la persiste usando el almacenamiento local y permite un acceso simple a su tienda a través de un captador .
Para usarlo, simplemente coloque el siguiente elemento Redux-Provider alrededor de su clase principal:
// ... Your other imports import PersistedStore from "./PersistedStore"; ReactDOM.render( <Provider store={PersistedStore.getDefaultStore().store}> <MainClass /> </Provider>, document.getElementById('root') );
y agregue la siguiente clase a su proyecto:
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;
fuente