Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSX props should not use .bind() - how to avoid using bind?

I have a container that I need to change the UI form showing the form or showing a success page.

The container has a state.showSuccess and I need the MyFormModule to be able to call the container to change the state.

The below code works but I'm getting the following warning:

JSX props should not use .bind()

How can I get this to work without using .bind()?

...
const myPage = class extends React.Component {
  state = { showSuccess: false };
  showSuccess() {
   this.setState({
      showSuccess: true,
    });
  }
  render() {
    const { showSuccess } = this.state;
    if (showSuccess) {...}
    ....
    <MyFormModule showSuccess={this.showSuccess.bind(this)} />
like image 828
AnApprentice Avatar asked Jan 05 '18 21:01

AnApprentice


People also ask

How do you avoid the need for binding in React?

To avoid the need for binding we have something introduced in ES6 as arrow functions. Using the arrow function to call this. setState will lead to avoid the use of bind.

Why JSX props should not use functions?

Using arrow functions or binding in JSX is a bad practice that hurts performance, because the function is recreated on each render. Whenever a function is created, the previous function is garbage collected. Rerendering many elements might create jank in animations.

Should you use BIND In React?

This is why we need to bind event handlers in Class Components in React. While working on React, you must have come across controlled components and event handlers. We need to bind these methods to the component instance using . bind() in our custom component's constructor.

Why is bind USED IN React?

Binding methods helps ensure that the second snippet works the same way as the first one. With React, typically you only need to bind the methods you pass to other components. For example, <button onClick={this.


2 Answers

You should first understand WHY this is a bad practice.

The main reason here, is that .bind is returning a new function reference.
This will happen on each render call, which may lead to a performance hit.

You got 2 options:

  1. Use the constructor to bind your handlers (this will run only once).

    constructor(props) {
      super(props);
      this.showSuccess = this.showSuccess.bind(this);
    }
    
  2. Or create your handlers with arrow functions so they will use the lexical context for this, hence you won't need to bind them at all (you will need a babel plugin):

    showSuccess = () => {
      this.setState({
        showSuccess: true,
      });
    }
    

You should not use this pattern (as others suggested):

showSuccess={() => this.showSuccess()}

Because this will as well create a new function on each render.
So you may bypass the warning but you are still writing your code in a bad practice design.

From the ESLint docs:

A bind call or arrow function in a JSX prop will create a brand new function on every single render. This is bad for performance, as it will result in the garbage collector being invoked way more than is necessary. It may also cause unnecessary re-renders if a brand new function is passed as a prop to a component that uses reference equality check on the prop to determine if it should update.

like image 169
Sagiv b.g Avatar answered Oct 19 '22 09:10

Sagiv b.g


Use an arrow function when defining showSuccess

showSuccess = () => {
  this.setState({
    showSuccess: true,
  });
} 
like image 28
Eric Hasselbring Avatar answered Oct 19 '22 09:10

Eric Hasselbring