I'm new to React and still learning. I'm trying to pass data from child to grandparent. So far I reach to parent and I`m stuck.
Child component:
export class Child extends React.Component{
constructor(props) {
super(props);
this.state= {
counterChild: 5
}
}
render() {
return(
<div>
<span>Child: {this.state.counterChild}</span><br />
<button onClick={this.props.data(this.state.counterChild)}>Click me</button>
</div>
);
}
}
Parent component:
export default class Parent extends React.Component{
constructor(props){
super(props);
this.state= {
counterParent: 0
}
}
updateParent(value) {
return() => {
this.setState({
counterParent: value
});
}
}
componentWillMount(){
this.props.data(this.state.counterParent)
}
render(){
return(
<div>
<span>Parent: {this.state.counterParent}</span>
<Child data={this.updateParent.bind(this)}/>
</div>
);
}
}
in child component i use a button and here i guess i have to use componentWillMount in order to send to grandparent..but it does not reach
Grandparent component:
export default class Grandparent extends React.Component{
constructor(props){
super(props);
this.state = {
counterGrandparent: 0
}
}
updateGrandparent(value){
return() => {
this.setState({
counterGrandparent: value
});
}
}
render(){
return(
<div>
<span>Grandparent: {this.state.counterGrandparent}</span>
<Parent data={this.updateGrandparent.bind(this)}/>
</div>
);
}
}
What did I do wrong here?
What you should do is: On the parent you have [state, setState] On the current component pass setStat as a prop to child component and then from child component pass setState as a prop to grandchild component. Then on grandchild component you can do something like: props. setState(array).
To emit event from grandchild to his grandparent component with Vue. js, we call $emit in the grand child component. Then in the parent component, we pass the events from the child to the grandparent with v-on="$listeners . And then we listen to the event emitted from the grandchild component in the grandparent.
As you may have figured out, data is passed down the component tree in the form of props, and up in the form of prop callback functions. When something happens in a child, you call the callback to inform the parent. The parent then updates its state and passes the new state to the child as a prop.
In your case, you have three nested components, each with their own state. Typically, only a parent "container" component will have state, and child components will be stateless. So let's remove the state from the Child and Parent components. The Child component interacts with the user with a button, so whenever the button is pushed, the event handler is called and the data flows up the tree using callbacks. I added some borders and padding to make the nesting clear:
Part of the problem lies in the onClick
handler on your button. Event handlers should be function references, but you have used a function call. So your child might be like below. Note the counter
prop that receives the current state, and the updateParent
prop that allows the Child to update the Parent.
import React from 'react';
const boxStyle = {
border: '1px solid red',
padding: '5px'
};
export class ChildWithButton extends React.Component {
handleClick(event) {
this.props.updateParent(this.props.counter + 1);
}
render() {
return(
<div style={boxStyle}>
<div>Child: {this.props.counter}</div>
<button onClick={this.handleClick.bind(this)}>
Add 1
</button>
</div>
);
}
}
The Parent component passes the current state down in the counter
prop, and lets the Child component change the state by calling the updateParent
callback that it received as a prop:
export class Parent extends React.Component{
updateParent(value) {
this.props.updateGrandparent(value);
}
render() {
return(
<div style={boxStyle}>
<div>Parent: {this.props.counter}</div>
<ChildWithButton
counter={this.props.counter}
updateParent={this.updateParent.bind(this)} />
</div>
);
}
}
The Grandparent component holds the state, passing it down to the Parent in counter
and allowing it to update it with updateGrandparent
. It should be noted that Grandparent has no knowledge of Child, only of Parent.
export default class Grandparent extends React.Component {
constructor(props) {
super(props);
this.state = {counter: 5};
}
updateGrandparent(value){
this.setState({counter: value});
}
render() {
return (
<div style={boxStyle}>
<div>Grandparent: {this.state.counter}</div>
<Parent
counter={this.state.counter}
updateGrandparent={this.updateGrandparent.bind(this)} />
</div>
);
}
}
You should avoid using componentWillMount
as it will be removed in a future version of React.
You should also name the function you pass down in props something other than data
. Function names are typically verbs.
There was more than one thing wrong with your code, so I hope this answers your question.
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