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?
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] = ...
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With