javascript - Where should I bind methods in React component? - Stack Overflow

I learn React now and noticed that a lot of people bind their methods in constructor. Like this:class M

I learn React now and noticed that a lot of people bind their methods in constructor.

Like this:

class MyComponent extends React.Component {
  constructor() {
    super();
    this.myMethod = this.myMethod.bind(this);
  }

  render() {
    <button onClick={this.myMethod}>Click me</button>
  }

  myMethod() {
    // do something
  }
}

But I got used to writing something like this:

render() {
    <button onClick={this.myMethod.bind(this)}>Click me</button>
}

And I was told by a couple of people that using the second method is a bad experience.

So could you tell me the differences between first and second methods? Any pros and cons? or performance issues?

I learn React now and noticed that a lot of people bind their methods in constructor.

Like this:

class MyComponent extends React.Component {
  constructor() {
    super();
    this.myMethod = this.myMethod.bind(this);
  }

  render() {
    <button onClick={this.myMethod}>Click me</button>
  }

  myMethod() {
    // do something
  }
}

But I got used to writing something like this:

render() {
    <button onClick={this.myMethod.bind(this)}>Click me</button>
}

And I was told by a couple of people that using the second method is a bad experience.

So could you tell me the differences between first and second methods? Any pros and cons? or performance issues?

Share Improve this question edited Mar 17, 2019 at 2:23 Cœur 38.8k25 gold badges205 silver badges277 bronze badges asked Sep 5, 2018 at 18:15 Dils MatchanovDils Matchanov 5771 gold badge7 silver badges21 bronze badges 5
  • 3 Any impact in performance caused by this would be minimum. It's more about having less javascript code in your JSX, making it more readable. – Phiter Commented Sep 5, 2018 at 18:17
  • 1 From what I understood in the second example you are binding and creating a new function every time render is called, but as I am not sure about this, if anyone knows if its right or not, feel free to correct me. – Bruno Mazzardo Commented Sep 5, 2018 at 18:19
  • 1 @BrunoMazzardo you are correct. a new function is created every time render is called. This will cause children that rely on the prop to re-render because of the new object being a change. – emran Commented Sep 5, 2018 at 18:23
  • Nice, I remend this link to see others approach this problem medium.freecodecamp/… – Bruno Mazzardo Commented Sep 5, 2018 at 18:25
  • This topic is discussed ad infinitum in so many other resources about React that you can find on the web that it's really unnecessary here – Dexygen Commented Sep 5, 2018 at 18:25
Add a ment  | 

6 Answers 6

Reset to default 4

You are right and what others told you is also right.

You are encouraged to do binding in constructor because constructor gets called only once per ponent so if you do binding in constructor it creates a new object/function only once in Webpack bundle.js file hence not much impact

You are not encouraged to do binding directly in render because a ponent renders for several reasons like when you do setState, when your ponent receives new props so your ponent will render so many times. So since you are binding directly in render whenever your ponent renders it will create a new function every time in Webpack bundle.js and your bundle file size will increase and that affects performance when your app contains thousands of ponents and if you do binding directly in render in every ponent.

So you are remended to do binding only in constructor. Hope that clarifies

This results in creating a new bound function on every render call:

render() {
    <button onClick={this.myMethod.bind(this)}>Click me</button>
}

Notice that if myMethod is used in multiple places, this requires multiple bind calls and may result in unbound callback if one of bind is missing.

While this creates bound function on ponent instantiation:

  constructor() {
    super();
    this.myMethod = this.myMethod.bind(this);
  }

The second option is remended.

A decorator like autobind can be used to skip myMethod explicit assignment in constructor.

As explained in this answer, prototype methods with bind have less shortings than arrow instance methods and can be generally preferred.

You should bind in the constructor simply because the second way will create a new function every render.

But there's a better way to simply avoid binding. Use arrow function.

class MyComponent extends React.Component {
  constructor() {
    super();
  }

  render() {
    <button onClick={this.myMethod}>Click me</button>
  }

  myMethod = ()=> {
    // do something
  }
}

Let's see how the creator of Redux Dan Abramov thinks about bind vs arrow functions -

Question:

In terms of performance, is there any difference between using arrow functions and bind manually when using es6 classes? Using arrow functions the methods are not on the class prototype, it will be on the class instance only. Using bind will attach the methods to class prototype. It sounds like bind manually will have better performance, does that mean we should consider using bind instead of arrow functions for class methods?

Any suggestions or ments are really appreciated!

So in terms of performance, would you remend using

class MyComponent extends React.Component { constructor(props) { super(props) }

methodA = () => { ... } }

or

class MyComponent extends React.Component { constructor(props) { super(props) this.methodA = this.methodA.bind(this) }

methodA() { ... } }

Answer:

These two ways of writing it are equivalent. (The second one is piled to the first one.)

Using bind will attach the methods to class prototype.

In your example, you still attach the function to the instance:

this.methodA = this.methodA.bind(this)

So they’re essentially the same.

At Facebook, we use the second way (“class properties”) but be aware this is still experimental, and not part of ES6. If you only want to stick with stable syntax, then you could bind them manually.

First approach is correct performance wise, because on every render this onClick prop will be pointing to the same object, which is not the case in the second example.


If you look at the below example, you will see when I increment the counter, the MyPureCompOne doesn't render, but MyPureCompTwo does. Because each time time the <App> ponent renders, MyPureCompTwo props handleClick being assigned with a new function object, and that is why being a pure ponent shallow parisons of props are false and it renders. This rendering was not needed. But that is not the case with MyPureCompOne, as each time time App renders, the handleClick props still pointing to the same function object (this.handleClickOne) which was created when the App first time mounted.

class MyPureCompOne extends React.PureComponent {
  render() {
    console.log("rendring ponent one");
    return <button onClick={this.props.handleClick}>First Button</button>
  }
}

class MyPureCompTwo extends React.PureComponent {
  render() {
    console.log("rendring ponent two");
    return <button onClick={this.props.handleClick}>Second Button</button>;
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
    this.handleCountChange = this.handleCountChange.bind(this);
    this.handleClickOne = this.handleClickOne.bind(this);
  }

  handleCountChange() {
    this.setState(prevState => ({
      count: prevState.count + 1
    }));
  }

  handleClickOne(e) {
    console.log("Clicked..");
  }

  handleClickTwo() {
    console.log("Clicked..");
  }

  render() {
    const { count } = this.state;
    return (
      <div>
        <button onClick={this.handleCountChange}>Change Counter</button>
        <MyPureCompOne handleClick={this.handleClickOne} />;
        <MyPureCompTwo handleClick={this.handleClickTwo.bind(this)} />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg./react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg./react-dom@16/umd/react-dom.production.min.js"></script>


<div id='root'></div>

I took this from the eslint-plugin-react documentation:

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 ponent that uses reference equality check on the prop to determine if it should update.

As a side note from me, using this in your JSX can be confusing as well. I encourage you to take a look at this doc: https://github./yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md

You should avoid arrow functions and binds in render. It breaks performance optimizations like shouldComponentUpdate and PureComponent.

For an excellent read and demo you might want to refer this.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744290458a4567005.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信