8

passing data from child to parent component via callback function but somehow it's not working. what am I doing wrong here? passing data from child to parent component - react - via callback function

https://codepen.io/silentarrowz/pen/GEMQEP?editors=0010

and here's the code

class App extends React.Component{
    constructor(props){
      super(props);
      this.state={
        input:'this is the input for now'
      }
   //this.handleInput=this.handleInput.bind(this);   
    }

    handleInput(x){
      this.setState({
        input:x
      });
      alert(this.state.input);
    }

  render(){
    return(
      <div>
        <h1>Passing props from Child to Parent Component</h1>
        <Child getInput={this.handleInput} />
        here's the input: {this.state.input}
        </div>
    );
  }
 }

class Child extends React.Component{
  constructor(){
    super();
    this.state={
      text:''
        }
    }
  passingProps(e){
    var newInput=e.target.value;
    //alert(newInput);
   this.setState({
     text:newInput
    });
  this.props.getInput(this.state.text);
  }

  render(){
    return(
      <div>
      <input type="text" placeholder="please input a name..." onChange={this.passingProps} />

        </div>

    )
  }
}

ReactDOM.render(
  <App/>,
  document.getElementById('app')
);
Todd Mark
  • 1,847
  • 13
  • 25
faraz
  • 2,603
  • 12
  • 39
  • 61

6 Answers6

6

There are a couple of issues.

1) You have to bind passingProps

constructor(){
    super();
    this.state={
      text:''
    }
    this.passingProps = this.passingProps.bind(this);
}

2) this.setState is asynchronous, so it's not guaranteed that this.state.text will be set to the value you want by the time you pass it to this.props.getInput. You can either do

this.props.getInput(newInput)

or

this.setState({ text: newInput }, () => {
  this.props.getInput(this.state.text);
})

to resolve that issue.

DonovanM
  • 1,174
  • 1
  • 12
  • 17
  • thanks. that really helped a lot. I didnt know setState is asynchronous – faraz Jun 26 '17 at 06:43
  • @DonovanM hi I'm having a similar issue,but this isn't solving my problem – John Anisere Oct 25 '17 at 14:41
  • @JohnAnisere what issue are you having? It'll probably be easier to add a new question – DonovanM Oct 26 '17 at 16:09
  • @DonovanM What if the child class is a function instead of a class? Can you assist me https://codesandbox.io/s/exciting-architecture-qkldm?file=/src/FieldData.js – JayC Jan 12 '21 at 21:04
2
class App extends React.Component{
constructor(props){
  super(props);
  this.state={
    input:'this is the input for now'
  }
  this.handleInput=this.handleInput.bind(this);   
}

handleInput(event){
  let value = event.target.value;
  this.setState({
    input:value
  });
}

render(){
   return(
     <div>
       <h1>{this.state.input}</h1>
       <Child getInput={this.handleInput} />
     </div>
   );
  }
}

 class Child extends React.Component{
   constructor(){
      super(props);
}

render(){
   return(
     <div>
     <input type="text" placeholder="please input a name..." onChange={this.props.getInput} />
    </div>

     )
   }
}

ReactDOM.render(
  <App/>,
  document.getElementById('app')
);

Here is the answer for your question. I hope your proplem is solved.

Vasi
  • 1,147
  • 9
  • 16
1

this is not automatically bound in your passingProps function. Try arrow function syntax to bind it.

passingProps = e => {
  var newInput=e.target.value;
  //alert(newInput);
  this.setState({
    text:newInput
  });
  this.props.getInput(this.state.text);
}
genestd
  • 384
  • 3
  • 16
1

In your Child Component, you have written following code:

passingProps(e){
  var newInput=e.target.value;
  //alert(newInput);
  this.setState({
     text:newInput
  });
  this.props.getInput(this.state.text);
}

The issue is due to the asynchronous behaviour of setState function. It means you can not call setState on one line and expect its updates on next line. Use the callback function of setState to call the function of parent component just like this:

passingProps(e){
  var newInput=e.target.value;
  //alert(newInput);
  this.setState({ text: newInput }, () => {
     this.props.getInput(this.state.text);
  })
}

Same thing is happening in handleInput function of App component.

Ritesh Bansal
  • 3,108
  • 2
  • 16
  • 23
1

Two things that you need to correct it:

  1. if you want to access new state, you don't use this.state.input after this.setState({input: 'xxx'}). Here is reason why not it.
  2. this.passingProps = this.passingProps.bind(this) is defined what this is current scope. when you use this in component's function, this need to be bind.

Changed codepen

Todd Mark
  • 1,847
  • 13
  • 25
1

You can create a method in parent that accepts some data and then sets the received data as parent state. Then pass this method to child as props. Now let the method accept child state as input and then let the method set the received child state as parent state.

Passing Child State to Parent

Community
  • 1
  • 1
Aftab22
  • 550
  • 6
  • 8