O primeiro princípio da documentação Redux é:
O estado de todo o seu aplicativo é armazenado em uma árvore de objetos dentro de um único armazenamento.
E eu realmente pensei que entendia bem todos os princípios. Mas agora estou confuso sobre o que significa aplicação.
Se aplicação significa apenas uma pequena parte complicada no site e funciona em apenas uma página, eu entendo. Mas e se a aplicação significar um site inteiro? Devo usar LocalStorage ou cookie ou algo para manter a árvore de estado? mas e se o navegador não suportar LocalStorage?
Eu quero saber como os desenvolvedores mantêm sua árvore de estados! :)
Respostas:
Se você quiser manter seu estado redux em uma atualização do navegador, é melhor fazer isso usando middleware redux. Verifique o middleware redux-persist e redux-storage . Ambos tentam realizar a mesma tarefa de armazenar seu estado redux para que possa ser salvo e carregado à vontade.
-
Editar
Já faz algum tempo que não revi essa pergunta, mas vendo que a outra (embora a resposta mais votada) incentiva a apresentação de sua própria solução, decidi responder novamente.
A partir desta edição, ambas as bibliotecas foram atualizadas nos últimos seis meses. Minha equipe tem usado redux-persist em produção há alguns anos e não teve problemas.
Embora possa parecer um problema simples, você descobrirá rapidamente que implementar sua própria solução não apenas causará uma carga de manutenção, mas resultará em bugs e problemas de desempenho. Os primeiros exemplos que vêm à mente são:
JSON.stringify
eJSON.parse
pode não apenas prejudicar o desempenho quando não é necessário, mas lançar erros que, quando não tratados em uma parte crítica do código, como sua loja redux, podem travar seu aplicativo.Para resumir, para 3kB minificado + gzipado (no momento desta edição), este não é um problema que eu pediria à minha equipe para resolver sozinho.
fonte
Editar 25 de agosto de 2019
Conforme afirmado em um dos comentários. O pacote redux-storage original foi movido para react-stack . Essa abordagem ainda se concentra na implementação de sua própria solução de gerenciamento de estado.
Resposta Original
Embora a resposta fornecida seja válida em algum ponto, é importante notar que o pacote redux-storage original foi descontinuado e não está mais sendo mantido ...
Agora, se você não quiser depender de outros pacotes para evitar problemas como esses no futuro, é muito fácil lançar sua própria solução.
Tudo que você precisa fazer é:
1- Crie uma função que retorne o estado de
localStorage
e então passe o estado para acreateStore
função redux do segundo parâmetro para hidratar a lojaconst store = createStore(appReducers, state);
2- Ouça as mudanças de estado e toda vez que o estado mudar, salve o estado para
localStorage
store.subscribe(() => { //this is just a function that saves state to localStorage saveState(store.getState()); });
E é isso ... Na verdade, eu uso algo semelhante na produção, mas em vez de usar funções, escrevi uma classe muito simples como abaixo ...
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 } }; } }
e então ao inicializar seu aplicativo ...
import StateLoader from "./state.loader" const stateLoader = new StateLoader(); let store = createStore(appReducers, stateLoader.loadState()); store.subscribe(() => { stateLoader.saveState(store.getState()); });
Espero que ajude alguém
Nota de Desempenho
Se as alterações de estado forem muito frequentes em seu aplicativo, salvar no armazenamento local com muita frequência pode prejudicar o desempenho do aplicativo, especialmente se o gráfico do objeto de estado para serializar / desserializar for grande. Para esses casos, você pode querer debounce ou estrangular a função que salva estado para localStorage usando
RxJs
,lodash
ou algo similar.fonte
Isso é baseado na resposta de Leo (que deve ser a resposta aceita, uma vez que atinge o propósito da pergunta sem usar libs de terceiros).
Eu criei uma classe Singleton que cria um Redux Store, persiste usando armazenamento local e permite acesso simples ao seu armazenamento por meio de um getter .
Para usá-lo, basta colocar o seguinte elemento Redux-Provider em torno de sua classe principal:
// ... Your other imports import PersistedStore from "./PersistedStore"; ReactDOM.render( <Provider store={PersistedStore.getDefaultStore().store}> <MainClass /> </Provider>, document.getElementById('root') );
e adicione a seguinte classe ao seu projeto:
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;
fonte