简体   繁体   English

使用ReactJS在ES6类中嵌套“ this”绑定

[英]Nested “this” binding in ES6 classes using ReactJS

Reading through React docs I came across the following piece of code : 通过阅读React文档,我遇到了以下代码

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

My question is this: 我的问题是这样的:

In componentDidMount() the arrow function () => this.tick() "captures" the enclosing this value and thus the proper tick method is called on the <Clock> component. componentDidMount() ,箭头函数() => this.tick() “捕获”包含this值的值,因此在<Clock>组件上调用了正确的tick方法。

However tick uses this on its own to subsequently call the setState method. 然而 tick使用this依靠自己的力量随后调用setState方法。 How is this working without any bindings? 没有任何约束,这如何工作? In other words, how is this.setState working? 换句话说, this.setState如何工作?

Thanks 谢谢

According to the bind function documentation , Function.prototype.bind will create a new function with the same body and scope as the original function, but where this in the scope of the new function refers to the argument that is passed into bind . 根据该bind函数文档Function.prototype.bind将创建一个相同的身体和范围作为原始功能的新功能,但是在this新功能的范围指的是传入参数bind This means you can pass a variable, lets say newContext into the bind function like: tick.bind(newContext) , and every instance of this inside of tick will be evaluated as newContext . 这意味着你可以通过一个变量,可以说newContextbind的功能,如: tick.bind(newContext)以及每一个实例this蜱内将被评估为newContext Although this is a keyword referring to the context of the scope, we have changed the scope's context and so this has a different value. 虽然this是指范围的上下文中的关键字,我们已经改变了范围的情况下,因此this具有不同的值。

The arrow notation does something similar, and will replace the this inside the value tick with the value of the context of the arrow function's scope. 箭头符号的作用类似,它将用箭头函数作用域的上下文的值替换值tickthis This is why the this keyword inside of tick does not have an undefined value. 这就是为什么tick内部的this关键字没有undefined值的原因。

I think Rajesh has already explained it in the comments, still I will give it a try to explain. 我认为Rajesh已经在评论中对其进行了解释,但我仍将尝试进行解释。

An arrow function does not create its own this context, so this has its original meaning from the enclosing context ie from where it is being called which is componentDidMount in your case. 箭头函数不会创建自己的上下文,因此它具有原始含义,即来自所包围的上下文,即从调用它的位置开始,在您的情况下为componentDidMount

  componentDidMount() {
    // this refers to React.Component instance
    this.timerID = setInterval(
      () => this.tick(),  // <----------------Same this is available here
      1000
    );
  }

If you use bind you can achieve similar things via setting context via bind. 如果使用绑定,则可以通过设置绑定上下文来实现类似的目的。

  componentDidMount() {
    // this refers to React.Component instance from inside cdm method
    this.timerID = setInterval(
      this.tick.bind(this),  // <----------------Same this is available here
     // We have set it react component instance via bind
      1000
    );
  }

Now after all those just look only at this method declaration - 现在,毕竟那些人只看这个方法声明-

  tick() {
    this.setState({
      date: new Date()
    });
  }

Upto this point we can not say exactly what will be the value of this inside tick . 高达这点我们不能说什么将是值this里面tick We also can not say that ' setState ' will be available on this or not. 我们也不能说“ setState ”将可在this与否。

Unless and until we see from where tick will get called and what execution context will be attached to tick at run time . 除非并且直到我们看到从哪里调用tick以及在运行时将附加哪些执行上下文附加到tick

Now if we see from where tick is getting called - componentDidMount . 现在,如果我们从哪里看到滴答声被称为componentDidMount componentDidMount is react component's life cycle method and it ( associated context ie this) definitely has setState method available. componentDidMount是反应组件的生命周期方法,并且它(关联的上下文,即此)肯定有setState方法可用。

And in componentDidMount we had set this to react-component context either via arrow function () => {} or via bind . 和在componentDidMount我们已经建立thisreact-component经由箭头函数上下文或者() => {}或经由bind This is the reason because of which setState is avaialble in tick when called and you don't see any error. 这是因为调用该setStatetick可用,而您看不到任何错误的原因。

But if you don't use arrow function or explicit bind you will be receiving following error on each time when setInterval calls tick function there by associating a global this with tick. 但是,如果不使用箭头函数显式绑定 ,则每次setInterval通过将全局this与tick关联而在其中调用tick函数时,都会收到以下错误。

  "message": "Uncaught TypeError: this.setState is not a function",

See the below code snippet via running to see the error 通过运行查看下面的代码片段以查看错误

 class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { // now this inside tick will be pointing to setIntervals execution context which could be global this.timerID = setInterval( this.tick, 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') ); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM