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:
function updateState(text){
this.setState({text})
}
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})
}
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>
)
}
}