本文介绍了React - 为什么在这个例子中不需要绑定 this?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
尝试了解 React 的基础知识.
看这个页面上的第二个例子:https://facebook.github.io/react/一>我看到 tick() 函数设置 Timer 类的状态,将先前的值加一.
class Timer 扩展 React.Component {构造函数(道具){超级(道具);this.state = {secondsElapsed: 0};}打钩() {this.setState((prevState) => ({secondsElapsed: prevState.secondsElapsed + 1}));}componentDidMount() {this.interval = setInterval(() => this.tick(), 1000);}componentWillUnmount() {clearInterval(this.interval);}使成为() {返回 (<div>已用秒数:{this.state.secondsElapsed}</div>);}}ReactDOM.render(, mountNode);
然而,当我尝试实现我自己的简单 Counter 类时,它失败了,我收到了一个控制台错误,说无法读取未定义的 setState 属性.
class Counter 扩展 React.Component {构造函数(道具){超级(道具);this.state = {count: 0};}增量(上一个状态){this.setState((prevState) => ({计数:prevState.count + 1}));}使成为() {返回 (<div className="main"><button onClick={this.increment}>{this.state.count}</button>
)}}
一些谷歌搜索表明我必须将它绑定到增量函数.但是为什么在我看到的第一个示例中不需要这样做?我将代码复制到 CodePen,它在 React 15.3.1 中运行良好,我在该示例中找不到任何类似于绑定的内容.只有在我在构造函数中添加绑定代码后,我的示例才开始工作.
class Counter 扩展 React.Component {构造函数(道具){超级(道具);this.state = {count: 0};//这一行解决了问题this.increment = this.increment.bind(this);}增量(上一个状态){this.setState((prevState) => ({计数:prevState.count + 1}));}使成为() {返回 (<div className="main"><button onClick={this.increment}>{this.state.count}</button>
)}}
解决方案
回答你的问题:第一个例子使用箭头函数
,自动执行上下文绑定.来自文档:
箭头函数不会创建自己的 this 上下文,因此它具有它的原始含义来自封闭上下文.
React 中确实有一些绑定方式:
1) 你可以绑定 构造函数中的所有函数,就像你说的:
构造函数(道具){/* ... */this.increment = this.increment.bind(this);}
2) 使用箭头函数调用回调:
this.increment(e)}>
3) 附加 .bind
每次将其设置为回调时,都在方法引用的末尾,如下所示:
4) 在你的类中,定义带有箭头函数的方法:
increment = (e) =>{/* 你的类函数定义为 ES6 箭头函数 */}/* ... */<button onClick={this.increment}>
为了在 babel 中使用这个语法,你必须启用这个 plugin 或使用 stage-2 预设.
Trying to figure out the basics of React.
Looking at the second example on this page: https://facebook.github.io/react/I see that the tick() function sets the state of the Timer class, incrementing the previous value by one.
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = {secondsElapsed: 0};
}
tick() {
this.setState((prevState) => ({
secondsElapsed: prevState.secondsElapsed + 1
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div>Seconds Elapsed: {this.state.secondsElapsed}</div>
);
}
}
ReactDOM.render(<Timer />, mountNode);
However, when I tried to implement my own simple Counter class, it failed and I got a console error saying Cannot read property setState of undefined.
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
}
increment(prevState) {
this.setState((prevState) => ({
count: prevState.count + 1
}));
}
render() {
return (
<div className="main">
<button onClick={this.increment}>{this.state.count}</button>
</div>
)
}
}
Some Googling reveals that I have to bind this to the increment function. But why was that not required in the first example that I saw? I copied the code to CodePen and it ran fine with React 15.3.1 I cannot find anything resembling binding in that example. Only after I added binding code in the constructor did things start working in my example.
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
// THIS ONE LINE FIXED THE ISSUE
this.increment = this.increment.bind(this);
}
increment(prevState) {
this.setState((prevState) => ({
count: prevState.count + 1
}));
}
render() {
return (
<div className="main">
<button onClick={this.increment}>{this.state.count}</button>
</div>
)
}
}
解决方案
Answering your question: the first example uses arrow functions
, that automatically performs context binding. From the docs:
Indeed there are some ways of binding in React:
1) you can bind all functions in your constructor, like you said:
constructor(props) {
/* ... */
this.increment = this.increment.bind(this);
}
2) invoke your callbacks with arrow functions:
<button onClick={(e) => this.increment(e)}>
3) append .bind
at the end of your method reference each time you set it as a callback, like this:
<button onClick={this.increment.bind(this)}>
4) In your class, define the method with arrow functions:
increment = (e) => {
/* your class function defined as ES6 arrow function */
}
/* ... */
<button onClick={this.increment}>
In order to use this syntax with babel, you have to enable this plugin or use stage-2 preset.
这篇关于React - 为什么在这个例子中不需要绑定 this?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!