95 lines
2.6 KiB
Plaintext
95 lines
2.6 KiB
Plaintext
== Why is this an issue?
|
|
|
|
Using `Function.prototype.bind` and arrows functions as attributes will negatively impact performance in React. Each
|
|
time the parent is rendered, the function will be re-created and trigger a render of the component causing excessive
|
|
renders and more memory use. Wrapping the function in a `useCallback` hook will avoid additional renders. This rule
|
|
ignores `Refs`. This rule does not raise findings on DOM nodes since that may require wrapping the DOM in a component.
|
|
Still, better performance can be achieved if this rule is respected in DOM nodes too.
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,javascript]
|
|
----
|
|
<Component onClick={this._handleClick.bind(this)}></Component>
|
|
|
|
<Component onClick={() => handleClick()}></Component>
|
|
----
|
|
|
|
=== Compliant solution
|
|
|
|
[source,javascript]
|
|
----
|
|
|
|
function handleClick() {
|
|
//...
|
|
}
|
|
|
|
<Component onClick={handleClick}></Component>
|
|
----
|
|
|
|
Situation can become more complicated when you need to pass additional parameters to the handler. Consider following
|
|
component printing the list of letters. Consider following non-compliant example
|
|
|
|
[source,javascript]
|
|
----
|
|
class Alphabet extends React.Component {
|
|
handleClick(letter) {
|
|
console.log(`clicked ${letter}`);
|
|
}
|
|
render() {
|
|
return (<div><ul>
|
|
{letters.map(letter =>
|
|
<li key={letter} onClick={() => this.handleClick(letter)}>{letter}</li>
|
|
)}
|
|
</ul></div>)
|
|
}
|
|
}
|
|
----
|
|
|
|
To avoid creating the arrow function you can factor out `li` element as separate child component and use `props` to pass
|
|
the `letter` and `onClick` handler.
|
|
|
|
[source,javascript]
|
|
----
|
|
class Alphabet extends React.Component {
|
|
handleClick(letter) {
|
|
console.log(`clicked ${letter}`);
|
|
}
|
|
render() {
|
|
return (<div><ul>
|
|
{letters.map(letter =>
|
|
<Letter key={letter} letter={letter} handleClick={this.handleClick}></Letter>
|
|
)}
|
|
</ul></div>)
|
|
}
|
|
}
|
|
|
|
class Letter extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.handleClick = this.handleClick.bind(this)
|
|
}
|
|
handleClick() {
|
|
this.props.handleClick(this.props.letter);
|
|
}
|
|
render() {
|
|
return <li onClick={this.handleClick}> {this.props.letter} </li>
|
|
}
|
|
}
|
|
----
|
|
|
|
alternatively you could rewrite `Letter` as a function and use `useCallback`
|
|
[source,javascript]
|
|
----
|
|
function Letter({ handleClick, letter }) {
|
|
const onClick = React.useCallback(() => handleClick(letter), [letter])
|
|
|
|
return <li onClick={onClick}>{letter}</li>
|
|
}
|
|
----
|
|
|
|
== Resources
|
|
|
|
* https://reactjs.org/docs/faq-functions.html[Passing Functions to Components] - React documentation
|
|
|