0

Apologies if this seems low effort but I have spent all day googling. I am trying to change the state of a date when a selection is made using the date picker. I am able to get this functionality to work by doing:

onDateChange={currentDate => this.setState({currentDate: currentDate})}

But if I try to turn this into a function:

onDateChange(currentDate) {
this.setState({currentDate: currentDate});

}

and then pass that function to onDateChange:

onDateChange={this.onDateChange}

This returns "cannot set state of undefined. The reason I am doing this is because I need the onDateChange function to execute in a parent component and then pass that prop down to this component. But I cannot even get the function to work in the child component. I have tried using an arrow function and but I am stumped. Can someone please tell me why this doesn't work as a function?

UPDATE:

Solved with

onDateChange={this.onDateChange} changed to {this.onDateChange.bind(this)}
Progman
  • 16,827
  • 6
  • 33
  • 48
  • 1
    `onDateChange={this.onDateChange}` can you try binding this `onDateChange={this.onDateChange.bind(this)}` – Dhiraj Dec 12 '19 at 21:29
  • Because, `onDateChange` does not know about `this` variable, so you either need to bind it like above or use an arrow function which is an es6 thing which takes care of this context – Dhiraj Dec 12 '19 at 21:34
  • @Lunamaxx you cannot pass an object method as a callback (in this case via React props but it's got nothing to do with React per se) and retain the correct `this` value. If you plan to keep writing Javascript you will definitely want to read up on the `this` keyword. – Jared Smith Dec 12 '19 at 21:37

1 Answers1

0

The arrow (or "fat arrow") in the 1st example passes in the proper this scope. The this is defined as you expect and the this has a setState method so it works.

In the 2nd example this ends up not being what you expect (i.e. undefined) and so it doesn't have a setState method and it fails, resulting in the error you reported.

I believe your 2nd example will be resolved if you add the binding below to your constructor:

class A extends Component {
  constructor(props) {
    ...
    this.onDateChange = this.onDateChange.bind(this);
    ...
  }
}

You may also be able to bind this when you instantiate the child component. That would be something like:

   <Child ... onDateChange={this.onDateChange.bind(this)} ... />

Source: https://reactjs.org/docs/faq-functions.html#how-do-i-bind-a-function-to-a-component-instance

WGriffing
  • 604
  • 6
  • 12
  • This answer is correct, but please do not answer duplicates. Flag them for closure. There are already a bunch of questions on SO that are exactly like this one. – Jared Smith Dec 12 '19 at 21:38
  • @jared-smith sorry about that. I don't think I have enough reputation to flag things yet. – WGriffing Dec 12 '19 at 21:45
  • Well, I just gave you a plus one to help you on your way. Keep writing quality answers like this (preferably on original questions obvs) and you'll get there quickly. – Jared Smith Dec 12 '19 at 21:51