Update State of a Component from Another in React
How to change state of child from parent, state of parent from child and state of sibling from another sibling
Introduction
As the title mention, this tip will discuss how to update the state of one component from another component in ReactJS. Components may have parent-child relation or sibling relation, there might be a hierarchy of children also, so this article will focus on mainly three relations - parent to child, child to parent and sibling to sibling.
Parent-Child
Parent to Child
We just have to write a function globally and bind it to the child. This function will be responsible for updating the state. Let's see how:
//this is the function responsible to update the state
function updateState(text){
this.setState({text})
}
//binding 'updateState' function with the child...
//now calling 'updateState' will update the child's state
constructor(props) {
super(props)
this.state = {
text: "Initial State"
}
updateState = updateState.bind(this)
}
The full code is as follows:
import React, { Component } from 'react';
import { style, primaryColor, secondaryColor } from '../style';
function updateState(text){
this.setState({text})
}
//passing state from parent to child
class Child1 extends Component {
constructor(props) {
super(props)
this.state = {
text: "Initial State"
}
updateState = updateState.bind(this)
}
render() {
return (
<div>
<div style={{ ...style.topLabel, color: primaryColor }}>I am Child</div>
<div style={style.label}>{this.state.text}</div>
</div>
)
}
}
class Parent extends Component {
constructor(props) {
super(props)
}
updateChild(text) {
updateState(text)
}
render() {
return (
<div>
<div style={{ ...style.topLabel, color: secondaryColor }}>I am Parent</div>
<input style={style.textBox} type="text"
placeholder="Write text" onChange={(e) => this.updateChild(e.target.value)} />
<Child1 />
</div>
)
}
}
export default Parent;
Child to Parent
It's very easy to update the state of the parent from any child, you just have to pass a callback function as props to that child and whenever it needs to update the state of parent, the function will be called. Let's see how it works:
class Child extends Component {
render() {
return (
<div>
<div style={{ ...style.topLabel, color: primaryColor }}>I am Child</div>
<input style={style.textBox} type="text"
placeholder="Write text" onChange={(e) => this.props.updateTextCB(e.target.value)} />
</div>
)
}
}
class Parent extends Component {
constructor(props) {
super(props)
this.state = {text: "Initial Text"}
this.updateText1 = this.updateText1
}
updateText1 = (text) => {this.setState({ text })}
render() {
return (
<div>
<div>I am Parent</div>
<div style={style.label}>{this.state.text}</div>
<Child updateTextCB={this.updateText1} />
</div>
)
}
}
Alternate Method
We can create a function outside the parent
class, bind it to the parent
and call the function from child
class when needed, similar to the previous case (parent to child). Let's see an example:
//
class Child extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<div>I am Child</div>
<input style={style.textBox} type="text" placeholder="Write text"
onChange={(e) => updateText2(e.target.value)} />
</div>
)
}
}
function updateText2(text) {
this.setState({ text })
}
class Parent extends Component {
constructor(props) {
super(props)
this.state = {
text: "Initial Text"
}
updateText2 = updateText2.bind(this)
}
updateText1 = (text) => {
this.setState({ text })
}
render() {
return (
<div>
<div>I am Parent</div>
<div style={style.label}>{this.state.text}</div>
<Child />
</div>
)
}
}
Sibling-Sibling
Similar to the 'parent to child' case, we will create a function and bind it the interested class and whenever needed, we will call that function from any other component. Let's have a look at one example:
class Sibling1 extends Component {
render() {
return (
<div>
<div style={{ ...style.topLabel, color: secondaryColor }}>I am Sibling 1</div>
<input style={style.textBox} type="text"
placeholder="Write text" onChange={(e) => updateText(e.target.value)} />
</div>
)
}
}
function updateText(text) {
this.setState({text})
}
class Sibling2 extends Component {
constructor(props) {
super(props)
this.state = {
text: "Initial State"
}
updateText = updateText.bind(this)
}
render() {
return (
<div>
<div style={{ ...style.topLabel, color: primaryColor }}>I am Sibling 2</div>
<div style={style.label}>{this.state.text}</div>
</div>
)
}
}
class Example3 extends Component {
render() {
return (
<div>
<Sibling1 />
<Sibling2 />
</div>
)
}
}