Onde escrever para localStorage em um aplicativo Redux?

Eu quero persistir algumas partes da minha tree de estado para o localStorage. Qual é o local apropriado para isso? Redutor ou ação?

O redutor nunca é um local apropriado para isso, pois os redutores devem ser puros e não têm efeitos colaterais.

Eu recomendaria apenas fazer isso em um assinante:

store.subscribe(() => { // persist your state }) 

Antes de criar a loja, leia as partes persistidas:

 const persistedState = // ... const store = createStore(reducer, persistedState) 

Se você usar o combineReducers() você notará que os redutores que não receberam o estado irão “inicializar” normalmente usando seu valor de argumento de state padrão. Isso pode ser muito útil.

É aconselhável que você debounce seu assinante para que você não grave no localStorage muito rápido, ou você terá problemas de desempenho.

Finalmente, você pode criar um middleware que encapsula isso como uma alternativa, mas eu começaria com um assinante porque é uma solução mais simples e faz bem o trabalho.

Para preencher os espaços em branco da resposta de Dan Abramov, você poderia usar o store.subscribe() assim:

 store.subscribe(()=>{ localStorage.setItem('reduxState', JSON.stringify(store.getState())) }) 

Antes de criar a loja, verifique o localStorage e analise qualquer JSON sob sua chave assim:

 const persistedState = localStorage.getItem('reduxState') ? JSON.parse(localStorage.getItem('reduxState')) : {} 

Você então passa esta constante peristedState para o seu método createStore assim:

 const store = createStore( reducer, persistedState, /* any middleware... */ ) 

Em uma palavra: middleware.

Confira o persistente do redux . Ou escreva o seu próprio.

[ATUALIZAÇÃO 18 de dezembro de 2016] Editado para remover a menção de dois projetos semelhantes agora inativos ou obsoletos.

Se alguém está tendo algum problema com as soluções acima, você pode escrever o seu próprio para. Deixe-me mostrar o que eu fiz. Ignore as coisas do saga middleware e concentre-se em duas coisas: localStorageMiddleware e reHydrateStore . o localStorageMiddleware todo o redux state do redux state e o coloca no local storage e o rehydrateStore obtém todo o applicationState no armazenamento local, se presente, e o coloca no redux store

 import {createStore, applyMiddleware} from 'redux' import createSagaMiddleware from 'redux-saga'; import decoristReducers from '../reducers/decorist_reducer' import sagas from '../sagas/sagas'; const sagaMiddleware = createSagaMiddleware(); /** * Add all the state in local storage * @param getState * @returns {function(*): function(*=)} */ const localStorageMiddleware = ({getState}) => { // < --- FOCUS HERE return (next) => (action) => { const result = next(action); localStorage.setItem('applicationState', JSON.stringify( getState() )); return result; }; }; const reHydrateStore = () => { // < -- FOCUS HERE if (localStorage.getItem('applicationState') !== null) { return JSON.parse(localStorage.getItem('applicationState')) // re-hydrate the store } } const store = createStore( decoristReducers, reHydrateStore(),// <-- FOCUS HERE applyMiddleware( sagaMiddleware, localStorageMiddleware,// <-- FOCUS HERE ) ) sagaMiddleware.run(sagas); export default store;