反应事件处理
考虑一个编辑框。用户键入一些文本。上附着有按键处理程序,它确实是这样的:反应事件处理
setState({echo: this.state.echo + event.char})
是否有可能在初始状态{echo: “”}
,用户键入“A”,然后“B”,阵营电话onKeyPress(“a”)
,这就要求setState({echo: “a”})
,和那么 - setState之前实际上是由React - React calls onKeyPress(“b”)
应用?
你看到一个问题,对吧? OnKeyPress(“b”)
会看到同样的老状态{echo: “”}
为OnKeyPress(“a”)
做,并会发出setState({echo: “”+“b”})
,这是setState({echo: “b”})
- 而我们显然是想{echo: “ab”}
- 我的测试表明我的第二个事件处理程序不会被调用之前,首先
setStat
e是完全处理。但是一些测试可能存在,不像一些记录在案的合同。 - 我意识到这个问题有解决方案,就像使用表格
setState(state => …)
- 但我仍想知道:这种情况是否可能。也许合成事件处理程序只能在所有待处理的
setState
处理(由前一个处理程序引起)完成时才被执行?如果是这样,我可以在哪里阅读一些证明?某些手册中的特定位置或Web上发布的合格答案...或者,也可能是相反的 - 这种保证不存在(但是,如果情况如此,setState的“简单”形式肯定会导致错误并且他们不应该允许这种形式)。
由于这是我第二次对类似问题没有明确答案,所以我只能推断出至少有上述场景的理论可能性。那么我们最好在所有情况下都遵循这个文档,并且只使用基于函数的setState来推断前一个状态的下一个状态。
这让我们走得更远。如果任何事件处理程序中有一些逻辑根据当前状态做出决定并设置新状态,则最好将其全部提取到方法并将整个方法传递给setState。这反过来又导致了一个关于提取所有这些方法以分离携带所有“真实”逻辑的组件的想法,原始组件仅留下标记和存根事件处理程序(并且没有任何状态),具有真实的逻辑和“状态”通过道具注入。对于表示和容器对象来说,采取或采取这种方法。 –
setState
将始终按顺序排列,但您给它的参数可以依赖于来自过去的状态。 setState
来电(例如来自您的两个按键)可以被合并并在下一个周期被呼叫。
这就是您在第二点提到的解决方案存在的原因,并且是解决此问题的正确方法。你在问题中描述的方式,简单地将状态值和按下的键进行连接,正是文档advise against。
授予,setState调用可以合并。但是如果知道下一次onKeyPress调用只会在处理完所有待处理的setState()调用后才会发生,那么这没有问题,因为这意味着唯一可合并的setState()调用是在同一个处理程序调用中执行的:onKeyPress calls setState然后再setState(也许间接),然后处理所有这些状态更改(可能在合并后),然后才调用下一个onKeyPress()。不管它是否已知 - 这正是我在这里问的问题。 –
我的意思是,如果我编写了这样一个代码,在同一个处理程序调用中执行多个setState调用,但不知道其异步特性,则是我的错。你只是不这样做:)但是无法在事件处理程序的多个后续调用中调用setState完全是另一回事。 –
好的,这个地方在你提到的文档中,它非常清楚我们不应该使用当前状态来组成新的状态。但是如果我们知道在调用下一个事件处理程序之前处理了所有未决的setState,或者类似的东西,那么我们可以说在这个特定的场景中我们可以使用当前状态。但是,当然如果不存在这样的信息,那么我们必须假定它是不安全的(就像文档通常所说的那样)。 –
我建议你利用组件生命周期方法componentDidUpdate和componentWillUpdate。在这些方法之间,会有一个渲染周期。这使您可以对已更改的事情做出回应。
尝试在捕获密钥时尝试将当前按键字符追加到现有字符串,请尝试在componentDidUpdate()中追加字符。
在这种情况下,您只需将当前按键存储在状态(例如currKey)中。然后在componentDidUpdate(),您可以添加这样的事情:
componentDidUpdate(prevProps, prevState) {
const { currKey, echo } = this.state;
if (currKey !== '') {
this.setState({
echo: echo + currKey, // append the current key to echo
currKey: '' // reset the current key
});
}
}
的的setState这里将触发另一次更新一轮,然而在这一轮currKey将是空的,这意味着直到另一个关键是逻辑将不再执行按下。
我想这可以完成,但正如我之前提到的(最近又做了一次),我意识到还有其他方法。但我在问这个特别的问题!如果知道这种情况是可能的,或者已知它是不可能的,或者没有确定的事情是已知的。 –
此外,我甚至不确定通过进一步进行状态更改来响应componentDidUpdate是个好主意。 –
我同意它可能是危险的,并且经常有林林规则警告它。但是,在这种情况下,它是安全的,不会产生无限循环。 –
你是否看到'setState'也接受一个具有前一状态的函数? –
“我意识到这个问题有解决方案,就像使用表单setState(state => ...)” –