I have a multi-step form application, and I'm struggling with getting my head around how I can save my redux state and replay it after a refresh for example? Going back/forward in the app works as expected, but after a browser refresh, my previous state is empty. Ideally I'd like to be able to save prior state in session storage relating to a path, so that I can replay later, but I'm not seeing how I can do that easily. Has anyone done anything like this and can provide some pointers? Thanks.
问题:
回答1:
It looks like you're trying to use a single-page app framework within a multiple-page context. To make the two play nicer together, you could look into making your own middleware that synchronizes state to and from localStorage
to create an app that appears to not have lost any state after a refresh/page navigation.
- Similar to the way that redux-logger logs both the previous and next states, I'd probably start by plugging in a middleware at the beginning (
localStorageLoad
) and end (localStorageDump
) of thecreateStoreWithMiddleware
function creation (right beforeredux-logger
):
// store/configureStore.js
const createStoreWithMiddleware = applyMiddleware(
localStorageLoad, thunk, promise, localStorageDump, logger
)(createStore);
- Then fire an initial action right when you initialize your app to load stored state before your app renders:
// index.js
const store = configureStore();
store.dispatch({ type: 'INIT' });
ReactDOM.render(<App />, document.getElementById('root'));
The localStorageLoad
would handle the INIT
action and dispatch some sort of SET_STATE
action, which would contain a payload with the state that was previously saved in localStorage
.
// middleware/localStorageLoad.js
export default store => next => action => {
const { type } = action;
if (type === 'INIT') {
try {
const storedState = JSON.parse(
localStorage.getItem('YOUR_APP_NAME')
);
if (storedState) {
store.dispatch({
type: 'RESET_STATE',
payload: storedState
});
}
return;
} catch (e) {
// Unable to load or parse stored state, proceed as usual
}
}
next(action);
}
Then, add a reducer which replaces the state with that payload, effectively rebooting the app as it was previously.
- To complete the loop, you'd need a
localStorageDump
middleware that comes at the end of the chain that saves each reduced state object intolocalStorage
. Something like this:
// middleware/localStorageDump.js
export default store => next => action => {
const state = store.getState();
localStorage.setItem('YOUR_APP_NAME', JSON.stringify(state));
next(action);
}
Just an idea, haven't actually tried it. Hope that helps get you started towards a solution.
回答2:
You can't store state on refresh this is normal. Typically you store these inside cookies or web storage.
- Cookies are synced between browser, server and are set on every request you perform.
- Localstorage gives you up to 5MB to store data in and never gets send with the request.
Redux:
- Set localstorage properties when filling in form. (be sure to clean it when complete)
- Refresh the page with an incomplete form.
- When react mounts your
Form
component, usecomponentWillMount
method to read thelocalstorage
anddispatch
the data to a reducer - The reducer updates the redux-state which in turn updates the component with the properties you got from localstorage.
If you use redux to store form data dispatch the properties of localstorage.
If not read the localstorage inside the Form
component and set the initial values.
Hope this helps !