使用 ReactJS 在 ES6 类 中嵌套 "this" 绑定
Nested "this" binding in ES6 classes using ReactJS
阅读 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()
"captures" 封闭的 this
值,因此在 [=17= 上调用了正确的 tick
方法] 零件。
但是 tick
单独使用 this
随后调用 setState
方法。在没有任何绑定的情况下,这是如何工作的?换句话说,this.setState
是如何工作的?
谢谢
根据bind
function documentation,Function.prototype.bind
将创建一个与原函数具有相同主体和范围的新函数,但新函数范围内的this
指的是传递给 bind
的参数。这意味着你可以传递一个变量,假设 newContext
进入 bind
函数,如:tick.bind(newContext)
,tick 内的每个 this
实例将被评估为 newContext
.尽管 this
是一个引用范围上下文的关键字,但我们更改了范围的上下文,因此 this
具有不同的值。
箭头符号做类似的事情,并将值 tick
中的 this
替换为箭头函数范围上下文的值。这就是 tick
中的 this
关键字没有 undefined
值的原因。
我想 Rajesh 已经在评论中解释过了,我还是会尝试解释一下。
箭头函数不会创建自己的 this 上下文,因此 this 在封闭上下文中具有其原始含义,即从调用它的位置开始,在您的情况下是 componentDidMount
。
componentDidMount() {
// this refers to React.Component instance
this.timerID = setInterval(
() => this.tick(), // <----------------Same this is available here
1000
);
}
如果您使用绑定,您可以通过绑定设置上下文来实现类似的事情。
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()
});
}
到目前为止,我们无法确切地说出 tick
中的 this
的值是多少。
我们也不能说“setState
”是否会在 this
上可用。
除非并且直到我们看到从哪里调用 tick
以及什么 执行上下文 将附加到 的 tick
运行时间.
现在,如果我们看到从哪里调用 tick - componentDidMount
。
componentDidMount
是 React 组件的生命周期方法,它(关联的上下文即 this)肯定有 setState
方法可用。
并且在 componentDidMount
中,我们通过箭头函数 () => {}
或 bind
将 this
设置为 react-component
上下文。
这就是调用时 setState
在 tick
中可用并且您看不到任何错误的原因。
但是如果你不使用 arrow function 或 explicit bind 你将在每次 setInterval
通过将全局 this 与 tick 相关联来调用 tick
函数。
"message": "Uncaught TypeError: this.setState is not a function",
通过运行查看下面的代码片段,查看错误
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>
阅读 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()
"captures" 封闭的 this
值,因此在 [=17= 上调用了正确的 tick
方法] 零件。
但是 tick
单独使用 this
随后调用 setState
方法。在没有任何绑定的情况下,这是如何工作的?换句话说,this.setState
是如何工作的?
谢谢
根据bind
function documentation,Function.prototype.bind
将创建一个与原函数具有相同主体和范围的新函数,但新函数范围内的this
指的是传递给 bind
的参数。这意味着你可以传递一个变量,假设 newContext
进入 bind
函数,如:tick.bind(newContext)
,tick 内的每个 this
实例将被评估为 newContext
.尽管 this
是一个引用范围上下文的关键字,但我们更改了范围的上下文,因此 this
具有不同的值。
箭头符号做类似的事情,并将值 tick
中的 this
替换为箭头函数范围上下文的值。这就是 tick
中的 this
关键字没有 undefined
值的原因。
我想 Rajesh 已经在评论中解释过了,我还是会尝试解释一下。
箭头函数不会创建自己的 this 上下文,因此 this 在封闭上下文中具有其原始含义,即从调用它的位置开始,在您的情况下是 componentDidMount
。
componentDidMount() {
// this refers to React.Component instance
this.timerID = setInterval(
() => this.tick(), // <----------------Same this is available here
1000
);
}
如果您使用绑定,您可以通过绑定设置上下文来实现类似的事情。
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()
});
}
到目前为止,我们无法确切地说出 tick
中的 this
的值是多少。
我们也不能说“setState
”是否会在 this
上可用。
除非并且直到我们看到从哪里调用 tick
以及什么 执行上下文 将附加到 的 tick
运行时间.
现在,如果我们看到从哪里调用 tick - componentDidMount
。
componentDidMount
是 React 组件的生命周期方法,它(关联的上下文即 this)肯定有 setState
方法可用。
并且在 componentDidMount
中,我们通过箭头函数 () => {}
或 bind
将 this
设置为 react-component
上下文。
这就是调用时 setState
在 tick
中可用并且您看不到任何错误的原因。
但是如果你不使用 arrow function 或 explicit bind 你将在每次 setInterval
通过将全局 this 与 tick 相关联来调用 tick
函数。
"message": "Uncaught TypeError: this.setState is not a function",
通过运行查看下面的代码片段,查看错误
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>