Search code examples
reactjslocal-storagereact-lifecycle

Setting the state in a component from localStorage


I'm building a multi-step form in React and one of my objectives is to save the user's input if they haven't finished filling in the form. I have saved the user's input in the browser's localStorage by using setItem().

The input fields set the local state which in turn get saved to the localStorage.

However, when the page is refreshed, I want to retrieve the data from localStorage and set the state variables from there so that it pre-fills the input fields with the saved data (if that makes sense)

I'm using setState() in componentDidMount() to do this, although I think that's creating an anti-pattern and I'm not entirely sure what that is. It works fine when I use UNSAFE_componentWillMount but I don't want to use a deprecated lifecycle method.

This is my code :

componentDidMount() {
    this.formData = JSON.parse(localStorage.getItem('form'));

    this.setState({
      type: this.formData.type,
      subtype: this.formData.subtype,
      brand: this.formData.brand
    })
  }

Solution

  • the idea to use componentDidMount is correct. There is another anti-pattern.

    1. Don't use this.formData = ... outside of component's constructor - https://reactjs.org/docs/react-component.html

    Whole working example would look like this. I added callback after setState to show that loading & saving to localStorage actually works.

    
    export default class Hello extends React.Component {
      state = {
        type: undefined,
        subtype: undefined,
        brand: 0,
      }
     
      componentDidMount() {  
        const formData = JSON.parse(localStorage.getItem('form')) ?? {};
        
        if (formData) {
          formData.brand += 5
    
          this.setState({
            type: formData.type,
            subtype: formData.subtype,
            brand: formData.brand,
          }, () => {
          console.log('newState', this.state) 
          localStorage.setItem('form', JSON.stringify(this.state))
          })
        } 
    
      }
      
      render() {
        return <h1>Hello {this.state.brand} </h1>
      }
    }