1

So I'm following the getting started guide for Redux Form and I've stumbled on this:

handleSubmit = (values) => { ... }

Intuitively I would think that it compiles to something as simple as this:

function handleSubmit(values) { ... }

But it does not. In reality it compiles to this:

handleSubmit = function handleSubmit(values) { ... };

This makes my JSlint go crazy (error Parsing error: Unexpected token =), though. And I've tried numerous ways to rewrite this including using the compiled JS instead, but when I do this I get an error because props cannot be accessed.

Can someone explain to me what is going on?

Here is the stacktrace when I use the compiled JS:

Uncaught TypeError: Cannot read property 'props' of undefined
    at handleSubmit (create.js:17)
    at doSubmit (handleSubmit.js:42)
    at handleSubmit.js:107
    at handleSubmit (handleSubmit.js:110)
    at Form.submit (reduxForm.js:540)
    at Object.ReactErrorUtils.invokeGuardedCallback (ReactErrorUtils.js:70)
    at executeDispatch (EventPluginUtils.js:85)
    at Object.executeDispatchesInOrder (EventPluginUtils.js:108)
    at executeDispatchesAndRelease (EventPluginHub.js:43)
    at executeDispatchesAndReleaseTopLevel (EventPluginHub.js:54)

And here is a gist with my Eslint config:

https://gist.github.com/webconsult/62bfa93054f261d92c186d39635f743c

zkwsk
  • 1,960
  • 4
  • 26
  • 34
  • Can you clarify exactly what warnings or errors you're getting? – Aron Mar 14 '17 at 09:36
  • Post your lint file config too. – Nevin Madhukar K Mar 14 '17 at 09:36
  • Possible duplicate of [What exactly does the anonymous JavaScript function f => f do?](http://stackoverflow.com/questions/41246164/what-exactly-does-the-anonymous-javascript-function-f-f-do) – evolutionxbox Mar 14 '17 at 09:38
  • 2
    _"Intuitively I would think that it compiles to"_ An assignment compiling to a declaration would be rather counter-intuitive. Running JSLint on compiled code is pretty pointless. – a better oliver Mar 14 '17 at 09:50

1 Answers1

1

I see in the link that the handleSubmit function is passed like this:

 <ContactForm onSubmit={this.handleSubmit} />

So, if you use the notation

function handleSubmit(values) { ... }

you are passing only the function definition, which will be called from inside the ContactForm component. When this happens, the 'this' keyword won't be scoped on the component you declare ContactForm on (ContactPage in this example), so you won't have access to the props.

Using the arrow notation

handleSubmit = (values) => { ... }

solves this because you are not passing the function definition but an instance of it, as this creates a class property with the instanced function. As arrow functions keep the scope of the 'this' keyword, when handleSubmit gets called, 'this' will be correctly scoped and you'll have access to the props of the component where you defined the callback.

Note that the same could be achieved declaring the handler as a class method instead of a property and binding the scope to it when passing it to the ContactForm:

class ContactPage extends React.Component {
  handleSubmit(values) {
    // Do something with the form values
    console.log(values);
  }
  render() {
    return (
      <ContactForm onSubmit={this.handleSubmit.bind(this)} />
    );
  }
}
  • Thanks for your explanation. I knew there was some difference in regards to `this` in arrow functions, but did not quite understand the implications. I also found this thread http://stackoverflow.com/questions/31362292/how-to-use-es6-arrow-in-class-methods which explains the issue a bit and I learned that I need a Babel plugin to do this reliably (it works on my machine not on Travis or on my colleagues machine). But since it is experimental I think I'll stick to passing `.bind(this)` for now. Thanks a lot! – zkwsk Mar 14 '17 at 12:39