diesel94
diesel94

Reputation: 159

LocalStorage in state of the component

I have two components Parent and Children. I want to see on my screen actual value of localStorage.getItem("myEl"). Parent state is storage:localStorage.getItem("myEl"). I change the "myEl" in localeStorage in Children component. Unfotunately Parent component not re-renders after "myEl" is changed but it works after I perform some action, such as changing the state again. I know that the problem is that setState is asinc but i don't know how to fix the problem.

For example,

Parent:

class Parent extends React.Component {

    constructor() {
        super();
        this.state = {storage:localStorage.getItem("myEl")};
    }

    render(){
        return <div>
                   <Child/>
                   <p>{this.state.storage}</p>
               </div>
    }
}

Child:

let i=0;
class Child extends React.Component {

render() {
    return (
            <button onClick={() => {
                localStorage.setItem("myEl",i);
                i++;
            }}>click me</button>
    );
}
}

Upvotes: 1

Views: 1458

Answers (2)

amdev
amdev

Reputation: 7460

Component should receive an state or prop in order to rerender itself, in your case it receive none of them. You should not update the localStorage and expect that your component is going to be reRendered with a new value from local storage, you could write a handler for your button in order to save the incremented value into your localstorage. Like below:

class App extends React.Component {

  constructor() {
    super()
    this.state = { _val: 0 }
  }

  componentDidMount = () => {
    const valFromLocalStorage = localStorage.getItem("myEl") || this.state._val
    this.setState({ _val: valFromLocalStorage })
  }

  handleINC = e => {
    const _valFromState = this.state._val
    const _val = _valFromState++
    localStorage.setItem("myEl", _val)
  }

  render() {
    return(
      <div>
       <button onClick={this.handleINC}>increment value!</button>
      </div>
    )
  }  
}

By the way, in componentDidMount you get the value from localStorage or if it was falsy you get the default value from your state. Then in button handler function you get the value from state and increment it and set it in your localStorage in case of component use cases in future, when user closes the tab and opens our website after a while the localstorage data is not been cleared, then this component will get the value from there.

Upvotes: 1

stasdes
stasdes

Reputation: 669

react is not listening to changes in localStorage that is why parent component don't know when child component changes the value in localStorage. To fix this you have to path your child component onClick function from parent this way:

class Parent extends React.Component {

    constructor() {
        super();
        this.state = {storage:localStorage.getItem("myEl")};
    }

    handleChildClick = (count) => {
      localStorage.setItem("myEl", count);
      this.setState({ storage:localStorage.getItem("myEl") });
    }

    render(){
        return <div>
                   <Child onClick={this.handleClick} />
                   <p>{this.state.storage}</p>
               </div>
    }
}
let i=0;
class Child extends React.Component {

render() {
    return (
            <button onClick={() => {
                this.props.onClick(i);
                i++;
            }}>click me</button>
    );
}
}

in case you need this value in other components consider using redux with react-redux containers to have a global storage available to you in any place of the react app.

Upvotes: 1

Related Questions