How to persist state in react class component for UI when I navigate or refresh the page

Viewed 415

Im trying to save the selection that is stored in the state and have it saved even after page navigation. I saw this is possible with using the local storage, which is preferred way for me. However, I saw plenty resource for doing this in a functional component, however, not for class components. So I gave it a try but its not even doing anything and still does not save the selection.

Background:, I have a state listView that is either true or false. So if listView is true, then the view would be listView. And if I switch it to false, and refresh the page, the listView boolean becomes true again. Same when I navigate to another page.

Here is my state: (after implementation)

this.state = {
      listView: JSON.parse(localStorage.getItem('listView')) || []
    };

And here is the handler to select(after implementation):

  renderListView = (selection) => {
    this.setState({
    listView: selection
  },() => {
    localStorage.setItem('listView', JSON.stringify(this.state.listView))
  });
  }

And here is where im calling it. Just in case you need to see it:

   <ToggleButtonGroup className={classes.toggleButtonContainer} exclusive orientation="horizontal">
            <ToggleButton className={listView ? classes.selectedToggleButton : '' } selected={listView} onClick={() => this.renderListView(true)} value="list" aria-label="list">
               <Icon fontSize="large" color="default">view_list</Icon>
            </ToggleButton>
            <ToggleButton className={!listView ? classes.selectedToggleButton : '' } selected={!listView} onClick={() => this.renderListView(false)} value="module" aria-label="module">
                <Icon fontSize="large" color="default">view_module</Icon>
            </ToggleButton>
        </ToggleButtonGroup>
2 Answers

You can use componentDidMount()

componentDidMount() {
 const listView = localStorage.getItem('listView')==='true';
  this.setState({listView});
}

If this does not work can you add your code to codeSandbox so that I can get what the exact issue is

The main issue is your initialization:

JSON.parse(localStorage.getItem('listView')) || []

If the value is stored as false then it is deemed falsy for the || operator, and thus the second operand [] is used. You could use ?? instead of || which checks for a nullish value (null or undefined) instead of a falsy value (null, undefined, false, 0, "", NaN).

JSON.parse(localStorage.getItem('listView')) ?? []

If "listView" is not yet set in local storage then null is returned and JSON.parse(null) will also evaluate to null. In which case the default value is used.

// when loading from local storage
false || [] //=> []
false ?? [] //=> false

// if local storage is not set
null || [] //=> []
null ?? [] //=> []
Related