Comments (12)
@rwieruch Yeah, I am not quite sure even after reading it.
From facebook:
The problem with this syntax is that a different callback is created each time the LoggingButton renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the property initializer syntax, to avoid this sort of performance problem.
What I understand from this is that creating a callback every time the component renders doesn't suffer from performance hit.
I understood why I needed to bind this - To make this work in the callback function, otherwise it will be undefined.
But the confusion for me was not knowing when I need to bind a method.
So I finally found it here again from facebook:
This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.
I guess I can use this as a reliable guideline :)
from the-road-to-learn-react.
As a beginner, trying to connect all elements together, I was obsessed with the 'binding' and 'context' things. And it confused me. But, unlike I thought, the purpose of the arrow function is not to do a binding there. Like @abuuzayr explained, it prevents the event handler inside the curly braces (onClick={<event handler>})
to get executed on the render() call.
What I missed is the difference between
onClick = {this.handleClick}
that is used in the official documentation, and
onClick = {this.handleClick()}
The first one works because it's not a function call but a reference to the function.
The second, because of the parenthesis, is a function call. And since we need to pass parameters inside the parenthesis
onDismiss(item.objectID)
we have to refer to the function an other way. Using an arrow function. Or defining the function outside the curly braces (but inside the map iteration, to pass the item.objectID parameters).
from the-road-to-learn-react.
I'm confused about the behavior of the handler when fired by the onClick event. In the official documentation in the 'Handling Event' part, we have
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
<button onClick={this.handleClick}>
works perfectly here and is not wrapped into another function. Maybe the reason we have to do it in this particular case (Robin tutorial) could be related with the fact that we are in a loop (map.(item => ...)? Which implies that each item has his proper 'context' and we have to bind the onDismiss function to the item context in order to have access to his properties (objectID in this case). And the possible way to bind the handler function to the context is to use an arrow function. Another is to define the function outside the loop (outside the render()). In other words, because of the iteration (map()) we have to do inside the loop the same 'binding' trick that we do in a classical handler. I'm not sure I'm clear ...
from the-road-to-learn-react.
<button onClick={this.handleClick}>
works perfectly here and is not wrapped into another function
this is because of the following :
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
Either you do explicit binding (because In JavaScript, class methods are not bound by default.) or you use property initializer syntax or arrow function.
from the-road-to-learn-react.
You're perfectly right. The point is since the binding is made in the constructor for the inDismiss method
constructor(props) {
super(props);
this.state = {
list,
};
this.onDismiss = this.onDismiss.bind(this);
}
why do we have to bind it again inside the render ?
<button
onClick={() => onDismiss(item.objectID)}
type="button"
>
It's not necessary in the React example above. My hypothesis is that since we are iterating a list of objects (the news), each <button/>
need to be bind with the context of his own item in order to access the properties (item.objectId).
render() {
const { list, pattern, onDismiss } = this.props;
return (
<div>
{ list.filter(isSearched(pattern)).map(item =>
<div key={item.objectID}>
...
<button
onClick={() => onDismiss(item.objectID)}
type="button"
>
Dismiss
</button>
</div>
)}
</div>
);
}
from the-road-to-learn-react.
In the React's doc (last paragraph) they encourage us avoiding the use of an arrow function as a callback for an event:
The problem with this syntax is that a different callback is created each time the LoggingButton renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the property initializer syntax, to avoid this sort of performance problem.
But here it is precisely the behavior we want for our list of news: create a different callback for each button associated with his own new thanks to the item.objectID parameter.
from the-road-to-learn-react.
ahh , my bad. I misunderstood what you were saying.
I don't think we need to bind in this particular case(code on page 33). We are already using an arrow function, so no need to bind.
From what I understand, arrow functions do have a performance overhead as you mentioned. One solution is to create a separate component which is what we do by the end of chapter 2.
from the-road-to-learn-react.
Totally right! Sorry for stepping in too late here. But I guess after struggling with the problem on your own, you really have internalized how it works now ๐
In the React's doc (last paragraph) they encourage us avoiding the use of an arrow function as a callback for an event:
That's right. It is not encouraged in the first place and there are ways around it. In the end, it is hard to keep the balance of keeping it simple for newcomers and teaching best practices from the beginning that would add complexity to the whole thing. But maybe it is something that could be refactored in an advanced chapter?
Thanks for all your input! I will definitely update this part in the next edition of the book, because I saw several people run into the issue while reading the book but also in personal workshops.
from the-road-to-learn-react.
Thanks! And bravo for your book: it's a very pleasant and stimulating road to learn React! ๐
from the-road-to-learn-react.
I also spent some time trying to understand different ways of passing arguments to an event handler. Using the ES6 arrow function makes it easy, but might have performance overheads.
One way is to use a sub component to achieve this. The main component will pass the argument and event handler to the child, and the child will simply call the handler with the argument, as seen here: https://stackoverflow.com/a/29810951
Another way mentioned is to curry the event handler with with the argument, then return another function containing the event object, as seen here: https://stackoverflow.com/a/45448802
For the first method, the flow of data is clear, however it takes more code/
For the second method, code is short and sweet, however it may not optimised?
What do you think?
from the-road-to-learn-react.
@hanchiang great additions, I will add these in the next edition.
Recently I heard more people arguing about the performance impacts of using inline arrow functions. But if you are not using these in dozens of components, the performance impact should be small. Nevertheless, it is great to teach people the best practices in the end. Thanks again everyone for your contribution.
from the-road-to-learn-react.
- Chapter about Bindings and Explanation about Arrow Function in Event Handler 69b2a46
- added performance implications b5bb077
from the-road-to-learn-react.
Related Issues (20)
- Translate to Spanish
- Typos HOT 3
- Verify and Fix: Functioning Binding Example HOT 1
- Translate to Vietnamese HOT 1
- Link Shortener HOT 1
- Index Page
- UX/A11Y: Improve Label
- A11Y: use button outline
- Source Code: Show after every Section rather than only every Chapter HOT 1
- Source Code Project: Folder/Folder Refactoring
- Source Code Project: Import/Export Statement
- Table component test failing in "Snapshot Tests with Jest" section HOT 1
- Hot Module replacement is not working ! Chapter 1 HOT 1
- Link redirection is no longer correct. HOT 1
- access a state object
- Translate to Thai HOT 1
- refs in stateless components HOT 1
- Would you mind to change the `bit.ly links` to direct links ? HOT 2
- Wikipedia MVC link in chapter1.md (line 9) shows รขโฌโ instead of dash (PDF version). Link broken.
- Translate to Persian
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from the-road-to-learn-react.