The first principle of Redux documentation is:
The state of your whole application is stored in an object tree within a single store.
And I actually thought that I understand all of the principles well. But I'm now confused, what does application mean.
If application means just one of little complicated part in a website and works in just one page, I understand. But what if application means the whole website? Should I use LocalStorage or cookie or something for keeping the state tree? But what if the browser doesn't support LocalStorage?
I want to know how developers keep their state tree! :)
When we refresh page in a web-app, the state always resets back to the initial values which in not a good thing when you try to build some large web-app like e-commerce. We can manually do the state persistent using the native JavaScript localStorage.
With the Redux Persist library, developers can save the Redux store in persistent storage, for example, the local storage. Therefore, even after refreshing the browser, the site state will still be preserved.
When creating your redux store, pass your createStore function a persistReducer that wraps your app's root reducer. Once your store is created, pass it to the persistStore function, which ensures your redux state is saved to persisted storage whenever it changes.
If you would like to persist your redux state across a browser refresh, it's best to do this using redux middleware. Check out the redux-persist and redux-storage middleware. They both try to accomplish the same task of storing your redux state so that it may be saved and loaded at will.
--
Edit
It's been some time since I've revisited this question, but seeing that the other (albeit more upvoted answer) encourages rolling your own solution, I figured I'd answer this again.
As of this edit, both libraries have been updated within the last six months. My team has been using redux-persist in production for a few years now and have had no issues.
While it might seem like a simple problem, you'll quickly find that rolling your own solution will not only cause a maintenance burden, but result in bugs and performance issues. The first examples that come to mind are:
JSON.stringify
and JSON.parse
can not only hurt performance when not needed but throw errors that when unhandled in a critical piece of code like your redux store can crash your application.To sum it up, for 3kB minified + gzipped (at the time of this edit) this is not a problem I would ask my team to solve itself.
As stated in one of the comments. The original redux-storage package has been moved to react-stack. This approach still focuses on implementing your own state management solution.
While the provided answer was valid at some point it is important to notice that the original redux-storage package has been deprecated and it's no longer being maintained...
The original author of the package redux-storage has decided to deprecate the project and no longer maintained.
Now, if you don't want to have dependencies on other packages to avoid problems like these in the future it is very easy to roll your own solution.
All you need to do is:
1- Create a function that returns the state from localStorage
and then pass the state to the createStore
's redux function in the second parameter in order to hydrate the store
const store = createStore(appReducers, state);
2- Listen for state changes and everytime the state changes, save the state to localStorage
store.subscribe(() => { //this is just a function that saves state to localStorage saveState(store.getState()); });
And that's it...I actually use something similar in production, but instead of using functions, I wrote a very simple class as below...
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 } }; } }
and then when bootstrapping your app...
import StateLoader from "./state.loader" const stateLoader = new StateLoader(); let store = createStore(appReducers, stateLoader.loadState()); store.subscribe(() => { stateLoader.saveState(store.getState()); });
Hope it helps somebody
If state changes are very frequent in your application, saving to local storage too often might hurt your application's performance, especially if the state object graph to serialize/deserialize is large. For these cases, you might want to debounce or throttle the function that saves state to localStorage using RxJs
, lodash
or something similar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With