Reputation: 159
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
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
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