Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ES6 class documentation with binding perf #6373

Merged
merged 1 commit into from
Mar 29, 2016

Conversation

mfunkie
Copy link
Contributor

@mfunkie mfunkie commented Mar 29, 2016

Adding a note in the ES6 class documentation about function binding. Recommending that you bind your handlers in the constructor so that they are referentially the same function every time render is invoked (helps with child components that might potentially call shouldComponentUpdate).

@gaearon
Copy link
Collaborator

gaearon commented Mar 29, 2016

It is a bit inconsistent that just before this paragraph we bind in the render() method. Maybe we can change that example instead of introducing the new one, and just repeat the constructor in this section instead?

@facebook-github-bot
Copy link

@mfunkie updated the pull request.

@mfunkie mfunkie force-pushed the patch-2 branch 2 times, most recently from 9dc9990 to e8d21d8 Compare March 29, 2016 18:04
@facebook-github-bot
Copy link

@mfunkie updated the pull request.

@@ -223,7 +224,14 @@ Counter.defaultProps = { initialCount: 0 };

### No Autobinding

Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` or [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `=>`.
Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` or [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `=>`. It is recommended that you bind your event handlers in the constructor over binding in the render function or using arrow functions so that a new function is not instantiated every render.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nits:

  • double space before It is
  • every render => on every render (IMO that reads better)

@facebook-github-bot
Copy link

@mfunkie updated the pull request.

@gaearon
Copy link
Collaborator

gaearon commented Mar 29, 2016

I read this a couple of times, and that sentence still stands out as too long to me.
I think we can do better and I have another idea.

  1. Change it to We recommend that you bind your event handlers in the constructor so they are only bound once for every instance:
  2. Change the example below to include the state assignment so reader doesn’t assume it can be removed for some reason.
  3. Before our new sentence, add an example demonstrating the previous (existing sentence), like
// You can use bind() to preserve `this`
<div onClick={this.tick.bind(this}>

// Or you can use arrow functions
<div onClick={() => this.tick()}>
  1. Finally, at the very end, add another one liner, a la Now you can use this.tick directly as it was bound once in the constructor. This is better for performance of your application:
// It is already bound in the constructor
<div onClick={this.tick}>

Sorry for the back and forth. What do you think of this?

@mfunkie
Copy link
Contributor Author

mfunkie commented Mar 29, 2016

The back and forth is good :) In fact, experimenting with this in the comments (because they're markdown anyways) is what I should have been doing in the first place. I want to sneak something in there mentioning why instantiating functions over and over is bad (shouldComponentUpdate). Before I commit and squash, how does this look?

Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind this to the instance. You'll have to explicitly use .bind(this) or arrow functions =>:

// You can use bind() to preserve `this`
<div onClick={this.tick.bind(this)}>

// Or you can use arrow functions
<div onClick={() => this.tick()}>

We recommend that you bind your event handlers in the constructor so they are only bound once for every instance:

constructor(props) {
  super(props);
  this.state = {count: props.initialCount};
  this.tick = this.tick.bind(this);
}

Now you can use this.tick directly as it was bound once in the constructor. This is better for performance of your application, especially if you compare props using shouldComponentUpdate:

// It is already bound in the constructor
<div onClick={this.tick}>

@gaearon
Copy link
Collaborator

gaearon commented Mar 29, 2016

This is looking great! Maybe worth changing “if you compare props using shouldComponentUpdate” to “if you implement shouldComponentUpdate() with a shallow comparison in the child components”.

@mfunkie
Copy link
Contributor Author

mfunkie commented Mar 29, 2016

Great idea. One last thing, what do you think about moving

"This is better for performance of your application, especially if you implement shouldComponentUpdate() with a shallow comparison in the child components."

to below the usage example?

e.g.

// It is already bound in the constructor
<div onClick={this.tick}>

This is better for performance of your application, especially if you implement shouldComponentUpdate() with a shallow comparison in the child components.

@gaearon
Copy link
Collaborator

gaearon commented Mar 29, 2016

👍 this makes more sense

<div onClick={this.tick}>
```

This is better for performance of your application, especially if you implement shouldComponentUpdate() with a [shallow comparison](https://facebook.github.io/react/docs/shallow-compare.html) in the child components.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s use a link from the root, i.e. [shallow comparison](/react/docs/...)

@facebook-github-bot
Copy link

@mfunkie updated the pull request.

}
```

Now you can use this.tick directly as it was bound once in the constructor:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s add some backticks for this.tick

@mfunkie mfunkie force-pushed the patch-2 branch 2 times, most recently from f3003cb to c5d2130 Compare March 29, 2016 19:39
@facebook-github-bot
Copy link

@mfunkie updated the pull request.

<div onClick={this.tick}>
```

This is better for performance of your application, especially if you implement shouldComponentUpdate() with a [shallow comparison](/react/docs/shallow-compare.html) in the child components.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s make shouldComponentUpdate() a link to /react/docs/component-specs.html#updating-shouldcomponentupdate.

Adding a note in the ES6 class documentation about function binding.  Recommending that you bind your handlers in the constructor so that they are referentially the same function every time render is invoked (helps with child components that might potentially call shouldComponentUpdate)
@facebook-github-bot
Copy link

@mfunkie updated the pull request.

@gaearon gaearon merged commit 4910c3b into facebook:master Mar 29, 2016
@gaearon
Copy link
Collaborator

gaearon commented Mar 29, 2016

Thanks for your work on this! This will be up on the website soon.

@micky2be
Copy link

Good call

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants