How to maintain state after a page refresh in React.js?
Lets say I have code that sets state for a select box chosen on the previous page:
this.setState({selectedOption: 5});
Is there any way to have this.state.selectedOption
populated with 5 after a page refresh?
Are there callbacks that I can use to save this in localStorage and then do one large setState
or is there a standard way of doing something like this?
Solution 1:
So my solution was to also set localStorage
when setting my state and then get the value from localStorage
again inside of the getInitialState
callback like so:
getInitialState: function() {
var selectedOption = localStorage.getItem( 'SelectedOption' ) || 1;
return {
selectedOption: selectedOption
};
},
setSelectedOption: function( option ) {
localStorage.setItem( 'SelectedOption', option );
this.setState( { selectedOption: option } );
}
I'm not sure if this can be considered an Anti-Pattern but it works unless there is a better solution.
Solution 2:
You can "persist" the state using local storage as Omar Suggest, but it should be done once the state has been set. For that you need to pass a callback to the setState
function and you need to serialize and deserialize the objects put into local storage.
constructor(props) {
super(props);
this.state = {
allProjects: JSON.parse(localStorage.getItem('allProjects')) || []
}
}
addProject = (newProject) => {
...
this.setState({
allProjects: this.state.allProjects.concat(newProject)
},() => {
localStorage.setItem('allProjects', JSON.stringify(this.state.allProjects))
});
}
Solution 3:
We have an application that allows the user to set "parameters" in the page. What we do is set those params on the URL, using React Router (in conjunction with History) and a library that URI-encodes JavaScript objects into a format that can be used as your query string.
When the user selects an option, we can push the value of that onto the current route with:
history.push({pathname: 'path/', search: '?' + Qs.stringify(params)});
pathname
can be the current path. In your case params
would look something like:
{
selectedOption: 5
}
Then at the top level of the React tree, React Router will update the props
of that component with a prop of location.search
which is the encoded value we set earlier, so there will be something in componentWillReceiveProps
like:
params = Qs.parse(nextProps.location.search.substring(1));
this.setState({selectedOption: params.selectedOption});
Then that component and its children will re-render with the updated setting. As the information is on the URL it can be bookmarked (or emailed around - this was our use case) and a refresh will leave the app in the same state. This has been working really well for our application.
React Router: https://github.com/reactjs/react-router
History: https://github.com/ReactTraining/history
The query string library: https://github.com/ljharb/qs
Solution 4:
I consider state to be for view only information and data that should persist beyond the view state is better stored as props. URL params are useful when you want to be able to link to a page or share the URL deep in to the app but otherwise clutter the address bar.
Take a look at Redux-Persist (if you're using redux) https://github.com/rt2zz/redux-persist