Are react's lifecycle method autobound? If not should we be binding them with .bind(this)?

夙愿已清 提交于 2020-03-26 03:02:27

问题


I think the title is pretty self-descriptive.

I've building react components using the class notation, and I noticed that while handleSomething has to be manually bound to this, render and componentWillMount do not. Are method bound to this already? Is it ok to bind manually for notationally consistency's sake?


回答1:


Understanding of 'this' in JavaScript

The 'this' keyword in a function is determined by the executing scope of the function. For example, the this in someFunction when calling with obj.someFunction() will be obj.

A more concrete example:

function handleClick() {
    console.log(this.state.value);
}

var state = { value: 1 }; // declare a var in window
console.log("handleClick()");
handleClick(); // Logged 1. The 'this' in the method will be window, because the method is called in window


var obj = {
  state: { value: 2 },
  handleClick: function() {
    console.log(this.state.value);
  },
};
console.log("obj.handleClick();");
obj.handleClick(); // Logged 2. The 'this' is referred to obj because the method is called in obj.

// let's reassign the function to a temp var in window
var temp = obj.handleClick;
console.log("temp()");
temp(); // Logged 1. The 'this' in the function is referred to window because the method is called in window.
console.log("window.temp()");
window.temp(); // this is equal to the one above.

console.log("temp.bind(obj)");
temp.bind(obj)(); // Logged 2. Bind the method and call the method, so the 'this' in the function is referred to obj.

console.log("temp.bind(this)");
temp.bind(this)(); // Logged 1. Since this in the executing scope is window. This effectively is the same calling in this.

console.log("temp.bind(window)");
temp.bind(window)(); // Logged 1. This is equal to the one above.

Try it here: https://codepen.io/anon/pen/OvOpEa?editors=0012

A blog post about this: https://hackernoon.com/understanding-javascript-the-this-keyword-4de325d77f68

Back to your question

If you look at render, componentWillMount, and handleSomething you defined in your class, it will become apparent why you need to bind your handler to this.

render

// Rerender
ReactCurrentOwner.current = workInProgress;
var nextChildren = void 0;
{
  ReactDebugCurrentFiber.setCurrentPhase('render');
  nextChildren = instance.render();
  if (debugRenderPhaseSideEffects) {
    instance.render();
  }
  ReactDebugCurrentFiber.setCurrentPhase(null);
}

This is how react call redner(), where the instance is the object instance that has state, props, etc. You can try it very easily by putting a breakpoint in your render method and go back a call stack.

handleSomething

For example, if you define your class like this, with handleSomething as the onClick callback method of the button.

class Button extends Component {
  handleSomething() {
    // 'this' will be undefined.
  }

  render() {
    return (<button onClick={this.handleSomething}>Test</button>);
  }
}

If you click the button, this is how react calls the onClick handler method.

  function callCallback() {
    fakeNode.removeEventListener(evtType, callCallback, false);
    // This is where react calls your method.
    func.apply(context, funcArgs);
    didError = false;
  }

where func is handleSomething, and context is usually undefined in my debugging experience, and funcArgs is the arguments that being passed in the function.

apply is similar to bind. The first argument is used to specify the this of the function, and the second argument is an array of parameters to pass into the function.

See MDN for more information about apply: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

In this case, the method handleSomething is being called with undefined as this; Therefore, if you didn't bind the method, your this will be undefined.

I noticed that while handleSomething has to be manually bound to this, render and componentWillMount do not. Are method bound to this already?

They are called with the instance of your class, so they already have this as your instance without using bind. I guess you can kind of say it's already bound to this.

Is it ok to bind manually for notationally consistency's sake?

You don't need to bind this with react's lifecycle methods. If you really want to, I guess you can bind those methods to this as well (there might be some side effects that I don't know, since I didn't really look that deeply into their source), but this is like doing obj.handleClick.bind(obj)(); instead of obj.handleClick();. It is unnecessary and will spend some clock cycles doing something that's not needed.



来源:https://stackoverflow.com/questions/49501775/are-reacts-lifecycle-method-autobound-if-not-should-we-be-binding-them-with-b

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!