Passing state between components is a common use case. Generally, we use a state management library like ​​Redux​​, for this purpose. But sometimes this is just an overkill. For small applications, we don’t require external state management libraries.

In this article, I will show you how passing of state is done by using only the core Reactjs features.


Pass State from Parent to Children

Since a child component is within the parent component, so we can pass the state as props of child. Look at this code –



export default class Parent extends React.Component{   state = {     name: 'Thor',     home: 'Asgard',   };    render(){     return(       <div>           <p>               Change Parent State - <br />               Name: <input type={'text'} value={this.state.name} onChange={(e) => this.setState({name: e.target.value})} />               home: <input type={'text'} value={this.state.home} onChange={(e) => this.setState({home: e.target.value})} />            </p>            <Child parentState={this.state} />       </div>     )   } }  class Child extends React.Component{   state = {     brother: 'Loki',     job: 'Being Awesome',   }   render(){     return (        <div>            <p>               Change Child State - <br />               Brother: <input type={'text'} value={this.state.brother} onChange={(e) => this.setState({brother: e.target.value})} />               Job: <input type={'text'} value={this.state.job} onChange={(e) => this.setState({job: e.target.value})} />            </p>            <p>                (Parent State Passed to Child) <br />                Name: {this.props.parentState.name} <br />                Home: {this.props.parentState.home}            </p>            <p>                (Child State) <br />                Brother: {this.state.brother} <br />                Job: {this.state.job}            </p>        </div>     )   } }



Here we have two components – ​​Parent​​​ and ​​Child​​​. We are passing ​​Parent​​​ state to the ​​Child​​​ using a prop parameter ​​parentState​​. If we make changes to the values of parent state, it will get reflected in the rendered JSX of child. See this code in action from below demo –

React js 参数传参2(转发)_React.js


Try to make changes in the input fields of above demo, you will see that changes will get reflected in the text. Although, ​​name​​​ and ​​home​​​ input fields are in ​​parent​​ component yet their values are passed to the child.


Pass State from Children to Parent

In order to pass anything from children to parent, we need to use the callbacks. Look at this code –


export default class Parent extends React.Component{   state = {     name: 'Thor',     home: 'Asgard',     brother: 'Loki',     job: 'Being Awesome',   };    childStateCallback = (childState) => {      this.setState({         brother: childState.brother,         job: childState.job,      });   }    render(){     return(       <div>           <p>               Change Parent State - <br />               Name: <input type={'text'} value={this.state.name} onChange={(e) => this.setState({name: e.target.value})} />               home: <input type={'text'} value={this.state.home} onChange={(e) => this.setState({home: e.target.value})} />            </p>            <p>                (Parent State Data) <br />                Name: {this.state.name} <br />                Home: {this.state.home}            </p>            <p>                (Child State passed to parent) <br />                Brother: {this.state.brother} <br />                Job: {this.state.job}            </p>            <Child toCallBack={(childState) => this.childStateCallback(childState)} />       </div>     )   } }  class Child extends React.Component{   state = {     brother: 'Loki',     job: 'Being Awesome',   }    setStateAndRunCallback = (val) => {       this.setState(val, () => {           this.props.toCallBack(this.state);       });   }    render(){     return (        <div>            <p>               Change Child State - <br />               Brother: <input type={'text'} value={this.state.brother} onChange={(e) => this.setStateAndRunCallback({brother: e.target.value})} />               Job: <input type={'text'} value={this.state.job} onChange={(e) => this.setStateAndRunCallback({job: e.target.value})} />            </p>        </div>     )   } }



In this code we have created a ​​childStateCallback​​​ function in ​​Parent​​​ component which is getting called from ​​Child​​​ component whenever its state gets updated. Pay attention that we are using the second parameter of ​​this.setState​​ to call our callback function. This second parameter ensures that our callback will run after the state gets updated successfully.

Also we are sending the child state directly to the parent which is a wrong practice. We should always send the copy of the state so that there is no risk of state mutation (Learn more about state mutation ​​here​​). But in our example we are not modifying the child state from parent so its completely safe.

React js 参数传参2(转发)_React.js_02



Calling Child Component Functions from Parent Component

With the help of reference variable, you can call child component function from parent component. Let’s understand this with the help of code –


  1. Class Based Components


export default class Parent extends React.Component{   constructor(props){      super(props);      this.childRef = React.createRef();   }    changeChildState = () => {      this.childRef.current.functionOfChildComponent('Loki');   }      render(){     return(       <div>           <button onClick={this.changeChildState}>This button press will update child state</button>           <Child ref={this.childRef} />       </div>     )   } }  class Child extends React.Component{   state = {     king: 'Thor',   }    functionOfChildComponent = (newKing) => {       this.setState({king: newKing});   }    render(){     return (        <div>            <p>               {this.state.king} is the real king of Asgard.            </p>        </div>     )   } }



Here we are creating a reference variable ​​this.childRef​​​ using ​​React.createRef()​​​ function. This is then used as ​​ref​​​ to the ​​Child​​​ component. Now with the click of button, we are calling a child method ​​functionOfChildComponent​​ and passing a value, ‘Loki’. This way we are accessing child function from parent component.


2. Functional Component – Calling through reference is a bit tricky in functional components since they do not support references. But we can get the work done by forwarding refs. Look at the code –


export default function Parent(){    const childRef = React.useRef();     const changeChildState = () => {      childRef.current.functionOfChildComponent('Loki');    }     return(       <div>           <button onClick={changeChildState}>This button press will update child state</button>           <Child ref={childRef} />       </div>     ) }  const Child = React.forwardRef((props, ref) => {     const [king, setKing] = React.useState('Thor');          React.useImperativeHandle(ref, ()=>({         functionOfChildComponent: (newKing) => {                                       setKing(newKing);                                   }     }));      return (        <div>            <p>               {king} is the real king of Asgard.            </p>        </div>     ) });



Let’s understand this code, step by step –

Step 1: Create Reference Variable

In functional component we can use ​​useRef()​​​ hook to create reference variable. In our code, we have created ​​childRef​​.

Step 2: Use ref in Child component

We are referring our Child component with ​​childRef​​​ variable in this line ​​<Child ref={childRef} />​​ .

Step 3: Enclose Child component in React.forwardRef function.

In this step we are simply enclosing our child component in React.forwardRef. So, suppose your component is like this –

const Component = (props) => {}

then after enclosing inside React.forwardRef, it will look like this –

const Component = React.forwardRef( (props, ref) => {} )

You can see that we have added ​​ref​​​ as parameter along with ​​props​​. This is important.


Step 4: Use ​​React.useImperativeHandle​​ function and list all the functions you wish to call as reference.

​React.useImperativeHandle​​ basically use the ref variable to make a link between reference variable and functions to be called. So, if your code is this –

const Component = (props) => {     const functionToBeCalled = () => {} }

then after using React.useImperativeHandle, it will look like this –

const Component = React.forwardRef(                                                           (props, ref) => {                        const functionToBeCalled = () => {}                         React.useImperativeHandle(ref, ()=>({                            functionToBeCalled: () => functionToBeCalled(),                        }));                     } )

Now check the whole working code in this demo –

React js 参数传参2(转发)_sed_03


That’s the end of this article. We have learned how to pass states between components and call functions of children from parent. Hope this information help you in your projects. If you have doubts or suggestions, please do let me know in comments. See you in the next article.