Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I update the parent's state in React?

My structure looks as follows:

Component 1   - |- Component 2    - - |- Component 4    - - -  |- Component 5  Component 3 

Component 3 should display some data depending on state of Component 5.

Since props are immutable, I can't simply save its state in Component 1 and forward it, right? And yes, I've read about Redux, but I don't want to use it. I hope that it's possible to solve it just with react. Am I wrong?

like image 397
Wojciech Kulma Avatar asked Feb 21 '16 14:02

Wojciech Kulma


People also ask

How do I change parent's state in React?

import React, { useLayoutEffect, useState } from 'react'; const App = () => { const [name, setName] = useState('Rahul'); return ( <div> {name} has email id of [email protected] <div> <Child name={name} change={setName} /> </div> </div> ); }; const Child = ({ name, change }) => { const [newName, setNewName] = ...

How do you update existing state in React?

To update our state, we use this. setState() and pass in an object. This object will get merged with the current state. When the state has been updated, our component re-renders automatically.

Can you update state directly React?

React will then look at the virtual DOM, it also has a copy of the old virtual DOM, that is why we shouldn't update the state directly, so we can have two different object references in memory, we have the old virtual DOM as well as the new virtual DOM.


2 Answers

For child-parent communication you should pass a function setting the state from parent to child, like this

 class Parent extends React.Component {   constructor(props) {     super(props)      this.handler = this.handler.bind(this)   }    handler() {     this.setState({       someVar: 'some value'     })   }    render() {     return <Child handler = {this.handler} />   } }  class Child extends React.Component {   render() {     return <Button onClick = {this.props.handler}/ >   } }  

This way the child can update the parent's state with the call of a function passed with props.

But you will have to rethink your components' structure, because as I understand components 5 and 3 are not related.

One possible solution is to wrap them in a higher level component which will contain the state of both component 1 and 3. This component will set the lower level state through props.

like image 120
Ivan Avatar answered Sep 27 '22 20:09

Ivan


I found the following working solution to pass the onClick function argument from the child to the parent component:

Version with passing a method()

//ChildB component class ChildB extends React.Component {      render() {          var handleToUpdate = this.props.handleToUpdate;         return (<div><button onClick={() => handleToUpdate('someVar')}>             Push me           </button>         </div>)     } }  //ParentA component class ParentA extends React.Component {      constructor(props) {         super(props);         var handleToUpdate = this.handleToUpdate.bind(this);         var arg1 = '';     }      handleToUpdate(someArg){         alert('We pass argument from Child to Parent: ' + someArg);         this.setState({arg1:someArg});     }      render() {         var handleToUpdate = this.handleToUpdate;          return (<div>                     <ChildB handleToUpdate = {handleToUpdate.bind(this)} /></div>)     } }  if(document.querySelector("#demo")){     ReactDOM.render(         <ParentA />,         document.querySelector("#demo")     ); } 

Look at JSFiddle

Version with passing an Arrow function

//ChildB component class ChildB extends React.Component {      render() {          var handleToUpdate = this.props.handleToUpdate;         return (<div>           <button onClick={() => handleToUpdate('someVar')}>             Push me           </button>         </div>)     } }  //ParentA component class ParentA extends React.Component {     constructor(props) {         super(props);     }      handleToUpdate = (someArg) => {             alert('We pass argument from Child to Parent: ' + someArg);     }      render() {         return (<div>             <ChildB handleToUpdate = {this.handleToUpdate} /></div>)     } }  if(document.querySelector("#demo")){     ReactDOM.render(         <ParentA />,         document.querySelector("#demo")     ); } 

Look at JSFiddle

like image 38
Roman Avatar answered Sep 27 '22 21:09

Roman