我搬到了Counter类外的函数addONe。这样的功能addOne后不工作了,但在另一边,我不接受任何错误。我的问题是我做错了什么,该常量addOne不工作?
import React from 'react';
const addOne = () => {
this.setState((prevState) => {
return {
count: prevState.count + 1
}
})
}
export default class Counter extends React.Component {
constructor(props) {
super(props);
this.minusOne = this.minusOne.bind(this);
this.reset = this.reset.bind(this);
this.state = {
count: 0
}
}
// addOne() {
// this.setState((prevState) => {
// return {
// count: prevState.count + 1
// }
// })
// }
minusOne() {
this.setState((prevState) => {
return {
count: prevState.count - 1
}
})
}
reset() {
this.setState(() => {
return {
count: 0// count: 0
}
})
}
render() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={this.addOne}>+1</button>
<button onClick={this.minusOne}>-1</button>
<button onClick={this.reset}>reset</button>
</div>
)
}
}
它不能正常工作。
你是你的函数内部访问this.setState
,但你没有任何setState
方法在你的范围,因为它是正确的React.Component
类的。
真正的问题是:你为什么要搬出类addOne
功能?
如果你正在学习,你需要一个更技术性的解释:)
首先,你需要访问setState
类的React.Component
方法之外呢,在你addOne功能。我们需要在this.setState
存在绑定到该函数的上下文。还有什么比组件本身的背景下更好?
让我们更新的渲染方法将下面一行:
<button onClick={this.addOne}>+1</button>
这一个:
<button onClick={addOne.bind(this)}>+1</button>
这里发生了什么事?功能addOne
被接收外部上下文(在这种情况下,this
)。这方面,将用作函数内this
关键字。技术上,结合另一种情况下创建一个新的有界函数,但是这是我们这里不关心另外一个问题。
如果您尝试这个小编辑它仍然是行不通的。
那是因为你作为一个lambda函数表达式声明addOne
。在ES6,lambda函数不能绑定了其他上下文。
事实上,如果你从一个lambda函数表达式将您addOne到函数声明,如下所示:
function addOne() {
this.setState(prevState => ({
count: prevState.count + 1
}));
}
...你会看到,增加正常工作:)
希望它可以帮助您了解是怎么回事。
保持ES6语法
现在,使用ES6拉姆达函数表达式不是impossibile,它只是移动了同样的问题有点人行道。我们不能绑定另一个方面,但我们可以保持关闭它调用驻留或具有正确的上下文中的方法。
例如,我们可以改变addOne
函数表达式为高阶函数,即采取setState
并返回你所需要的点击处理程序:
const addOne = setState => () =>
setState(prevState => ({
count: prevState.count + 1
}))
现在,在渲染方法,我们可能会认为这样使用它:
<button onClick={addOne(this.setState)}>+1</button>
传递setState
作为函数参照。
现在的微妙的问题是,setState
函数内addOne
没有它的原始环境的约束!
我们可以解决这个问题:
<button onClick={addOne(this.setState.bind(this))}>+1</button>
这些语法的行为如出一辙:
const addOne = setState => () =>
setState(prevState => ({
count: prevState.count + 1
}))
const addOne = setState => () =>
setState(prevState => {
return { count: prevState.count + 1 }
})
他们的工作是相同的,方式是因为拉姆达函数表达式,如果你有一个单独的语句作为函数体,该语句的评估结果自动返回。
这意味着,lambda函数可以短为:
const five = () => 5
// five() returns immediate value 5
说,当你有:
prevState => {
return { count: prevState.count + 1 }
}
要创建一个身体与返回平原对象的单个声明。
你看到的相似?您正在做同样的事情:有一个返回的东西单个语句。
可以拿出你记住的第一件事可能是重写它省略return
关键字,如:
prevState => {
count: prevState.count + 1
}
但是,这是行不通的。它会给你一个语法错误,由于是不应该存在的冒号。它不应该出现,因为如果一个lambda函数表达式体被定义为块(包装与{}
一切),它应该有一个以上的声明和,也许,一return
关键字。
为了使其工作,我们需要把普通对象定义为一个单独的语句,而我们做到这一点的包成圆形的括号,如:
prevState => ({
count: prevState.count + 1
})
再次,希望它有助于:)