javascript - react - ¿Dónde escribir a localStorage en una aplicación Redux?
localstorage vs sessionstorage (6)
Quiero persistir algunas partes de mi árbol de estado en localStorage. ¿Cuál es el lugar apropiado para hacerlo? ¿Reductor o acción?
En una palabra: middleware.
Echa un vistazo a redux-persist . O escribe el tuyo.
[ACTUALIZACIÓN 18 de diciembre de 2016] Editado para eliminar la mención de dos proyectos similares ahora inactivos o en desuso.
Llegué un poco tarde, pero implementé un estado persistente de acuerdo con los ejemplos aquí expuestos. Si desea actualizar el estado solo cada X segundos, este enfoque puede ayudarlo a:
-
Definir una función de contenedor
let oldTimeStamp = (Date.now()).valueOf() const millisecondsBetween = 5000 // Each X milliseconds function updateLocalStorage(newState) { if(((Date.now()).valueOf() - oldTimeStamp) > millisecondsBetween) { saveStateToLocalStorage(newState) oldTimeStamp = (Date.now()).valueOf() console.log("Updated!") } }
-
Llame a una función de contenedor en su suscriptor
store.subscribe((state) => { updateLocalStorage(store.getState()) });
En este ejemplo, el estado se actualiza como máximo cada 5 segundos, independientemente de la frecuencia con que se active una actualización.
No puedo responder a @Gardezi, pero una opción basada en su código podría ser:
const rootReducer = combineReducers({
users: authReducer,
});
const localStorageMiddleware = ({ getState }) => {
return next => action => {
const result = next(action);
if ([ ACTIONS.LOGIN ].includes(result.type)) {
localStorage.setItem(appConstants.APP_STATE, JSON.stringify(getState()))
}
return result;
};
};
const reHydrateStore = () => {
const data = localStorage.getItem(appConstants.APP_STATE);
if (data) {
return JSON.parse(data);
}
return undefined;
};
return createStore(
rootReducer,
reHydrateStore(),
applyMiddleware(
thunk,
localStorageMiddleware
)
);
la diferencia es que solo estamos guardando algunas acciones, podría utilizar una función antirrebote para guardar solo la última interacción de su estado
Para completar los espacios en blanco de la respuesta de Dan Abramov, puede usar
store.subscribe()
esta manera:
store.subscribe(()=>{
localStorage.setItem(''reduxState'', JSON.stringify(store.getState()))
})
Antes de crear la tienda, verifique
localStorage
y
localStorage
cualquier JSON bajo su clave de esta manera:
const persistedState = localStorage.getItem(''reduxState'') ? JSON.parse(localStorage.getItem(''reduxState'')) : {}
Luego pasa esta constante
peristedState
a tu método
createStore
esta manera:
const store = createStore(
reducer,
persistedState,
/* any middleware... */
)
Reductor nunca es un lugar apropiado para hacer esto porque los reductores deben ser puros y no tener efectos secundarios.
Recomendaría solo hacerlo en un suscriptor:
store.subscribe(() => {
// persist your state
})
Antes de crear la tienda, lea esas partes persistentes:
const persistedState = // ...
const store = createStore(reducer, persistedState)
Si usa
combineReducers()
notará que los reductores que no han recibido el estado se "arrancarán" normalmente usando su valor de argumento de
state
predeterminado.
Esto puede ser bastante útil.
Es recomendable que renuncies a tu suscriptor para que no escribas en localStorage demasiado rápido, o tendrás problemas de rendimiento.
Finalmente, puede crear un middleware que encapsule eso como una alternativa, pero comenzaría con un suscriptor porque es una solución más simple y funciona bien.
Si alguien tiene algún problema con las soluciones anteriores, puede escribir el suyo.
Déjame mostrarte lo que hice.
Ignora las cosas de
saga middleware
solo concéntrate en dos cosas:
localStorageMiddleware
y
reHydrateStore
.
localStorageMiddleware
todo el
redux state
y lo coloca en
local storage
y
rehydrateStore
extrae toda la
applicationState
localStorageMiddleware
en almacenamiento local si está presente y lo coloca en la
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;