Reputation: 2035
I had read the article about handle events in react with arrow functions. And the final way in that article is not likely the best because of re-render issue.
e.g.
class Example extends React.Component {
handleSelect = i => e => {
console.log(i)
}
render() {
return {this.state.language.map(item, i) => (
<ListItem
...
onPress={this.handleSelect(i)} // re-render sub component every time the Example render() because of the annoymous function
/>
)}
}
}
I wonder which way is the best to write event handler in React?
Upvotes: 3
Views: 655
Reputation: 19222
In order to get the best performance out of React, you need to minimize the number of objects that are being created during renders. And as a reminder a function declaration (e.g. function myFunc
or const func = () => {}
) creates an object.
I would say your code has an unsolvable issue because you're creating a new instance of the inner function when handleSelect
is invoked:
handleSelect = i => e => {
console.log(i)
}
I'll rewrite this using the function
notation because it's a bit more clear what happening (but I prefer arrow functions in practice):
handleSelect = function (i) {
return function (e) {
console.log(i);
}
}
The issue here is the with each render when you invoke handleSelect
it creates a brand new inner function (i.e. function (e) {/* ... */}
).
I mentioned that your code has an unsolvable issue because there is no way to split up your curried handleSelect
function because you're passing the index i
that's created inside the render function. Because that state doesn't exist anywhere else, you have to create a new function to close-over it every time and that's okay.
I would even refactor your code like so:
class Example extends React.Component {
// as @RickJolly mentioned, this method doesn't have to be arrow
handleSelect (i) {
console.log(i)
}
render() {
return {this.state.language.map(item, i) => (
<ListItem
...
onPress={() => this.handleSelect(i)}
)}
}
}
If you have to create a new function every time, then you might as well inline it vs returning a function. That's preference though.
Edit
As @RickJolly mentioned, if your method doesn't use this
then it shouldn't be an arrow function.
From his comment:
since you're calling
() => this.handleSelect(i)
via an arrow function,this
is bound to thethis
of the enclosing context [which is the class pointer]
Upvotes: 4