Managing state in a Reactjs Application can be complex when passing it between multiple components. This post addresses the way I passed state between child and parent components and how I managed to “lift state”.
It explains some of the things I wish I knew about state between multiple components and how I passed it down two components.
React JS State in a Nutshell
State is the basic way to update the UI and manage lifecycles of the frontend. The documentation does a good job of explaining how to implement it and it does a good job of explaining how it works.
Problems Managing State between Components
Being new to React, I didn’t understand how to implement state across components. I tried looking on stack overflow and all over the internet, especially at medium blog posts, for a solution, but couldn’t find exactly what I needed.
In words, I would explain state across multiple components in this way: State is managed on a component by component basis.
What does this mean. This means no matter if the component is the parent or the child, the component is responsible for its own state, whether passed and set from props or not.
Example
What does this look like. For me, I was passing a prop in when rendering the component from a Rails View and needed this property to go all the way to the most child component which was two components deep. Then I needed to update the state of the most parent element when the most child component’s state was updated.
If you are confused, here is an example:
class Parent extends Component {
constructor(props){
super(props);
this.state = {passedValue: this.props.passedFromStaticView};
this.handleParentStateUpdate = this.handleParentStateUpdate.bind(this);
}
// This method is passed as a prop to the child component
handleParentStateUpdate(e){
console.log("handle state update for the parent!")
// Sets the state of this class's passedValue variable
this.setState({passedValue: e})
}
render () {
return (
<React.Fragment>
<Child passedValue={this.state.passedValue} handleParentStateUpdate={this.handleParentStateUpdate} />
</React.Fragment>
);
}
}
class Child extends Component {
constructor(props){
super(props);
this.state = {passedValue: this.props.passedValue}
this.handleChildStateUpdate = this.handleChildStateUpdate.bind(this);
}
handleChildStateUpdate(e){
// Update the state of the Child Component
this.setState({passedValue: e})
// Calling the method that was passed down from the `Parent` class as a prop
this.props.handleParentStateUpdate(e)
}
render(){
return(
<React.Fragment>
<Child passedValueFromChild={this.state.passedValue} handleParentStateUpdate={this.handleChildStateUpdate} />
</React.Fragment>
)
}
}
class GrandChild extends Component {
constructor(props){
super(props);
this.state = {passedValue: this.props.passedValueFromChild}
this.handleChildStateUpdate = this.handleChildStateUpdate.bind(this);
}
handleChildStateUpdate(e){
// Update the state of the GrandChild Component
this.setState({passedValue: e})
// Calling the method that was passed down from the `Child` class as a prop
this.props.handleParentStateUpdate(e)
}
render(){
return(
<React.Fragment>
<button onClick={(e) => this.handleChildStateUpdate("State")} className="btn btn-warning">
Update State
</button>
</React.Fragment>
)
}
}
This can also be found on github as a gist.
More
Managing state is a little complex and can become daunting but the react library (w/o state management third party libraries like redux) makes it simple to manage state among multiple components with a little extra boilerplate code.