1

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
    })
  }
kal94
  • 15
  • 3

2 Answers2

1

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>
  }
}
  • I should've mentioned that I logged the state in the callback after setState and it works there but if I try and log it outside of the setState then its empty. Also your code works perfectly but it won't show on an attribute value on a component, eg `` – kal94 Jan 13 '22 at 11:33
  • `defaultInputValue` - seems that it may not react to the changes after the first render. `componentDidMount` is running AFTER the first render, so there may be a problem. A solution to this may be initializing the state in constructor or using a boolean flag to wait with rendering `Select` component after the `componentDidMount`. – Robert Sabisz Jan 13 '22 at 16:23
0

you can use constructor function if you do not want to retrieve local storage data in componentDidMount()

constructor(){
  const formData = JSON.parse(localStorage.getItem('form'));
  const { type, subtype, brand } = formdata; 
  this.setState({ type, subtype, brand });
}

Though I'd suggest to go with didMount.

componentDidMount() {
  const formData = JSON.parse(localStorage.getItem('form'));
  const { type, subtype, brand } = formdata; 
  this.setState({ type, subtype, brand });
}
Bilal Hussain
  • 994
  • 1
  • 10
  • 25