嵌套"这"使用ReactJS在ES6类中绑定

时间:2017-04-04 05:41:31

标签: javascript reactjs ecmascript-6 this es6-class

通过React文档阅读我遇到了following piece of code

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')
);

我的问题是:

componentDidMount()箭头功能() => this.tick()&#34;捕获&#34;括号this值因此在tick组件上调用正确的<Clock>方法。

然而 tick自行使用this来调用setState方法。如何在没有任何约束的情况下工作?换句话说,this.setState如何运作?

谢谢

2 个答案:

答案 0 :(得分:1)

根据bind function documentationFunction.prototype.bind将创建一个与原始函数具有相同主体和范围的新函数,但新函数范围内的this指的是传递给bind的参数。这意味着你可以传递一个变量,让我们说newContextbind函数中,如:tick.bind(newContext),并且tick内的this的每个实例都将被评估为{{1} }}。虽然newContext是一个引用范围上下文的关键字,但我们更改了范围的上下文,因此this具有不同的值。

箭头符号执行类似的操作,并将使用箭头函数范围的上下文值替换值this内的this。这就是tick内的this关键字没有tick值的原因。

答案 1 :(得分:1)

我认为Rajesh已经在评论中对此进行了解释,我仍然会尝试解释。

箭头函数不会创建自己的这个上下文,所以它在封闭的上下文中有其原始含义,即在你的情况下调用它的位置componentDidMount

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

如果你使用bind,你可以通过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
    );
  }

现在所有这些只是看一下这个方法声明 -

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

到目前为止,我们无法确切地说明thistick的价值。 我们也不能说'setState'可以在this上使用。

除非我们看到tick将被调用,执行上下文将在运行时附加到tick。< / p>

现在,如果我们看到tick被调用的地方 - componentDidMountcomponentDidMount是反应组件的生命周期方法,它(相关的上下文,即这个)肯定有setState方法可用。

componentDidMount我们已经通过箭头功能thisreact-component() => {}设置为bind个上下文。 这就是因为setState在调用tick时可以使用setInterval并且您没有看到任何错误的原因。

但是,如果您不使用箭头功能显式绑定,则每次tick调用 "message": "Uncaught TypeError: this.setState is not a function", 时都会收到以下错误通过将全局this与tick相关联来实现。

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>
import numpy as np

arr = np.array([1,2,3,4,5])
product = np.prod(arr+1) - 1
print product