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