javascript - 等待 setState 完成
问题描述
我从一百万个其他问题中看到,在调用 setState 后可以使用回调。事实上,我在questionChangeSystemCallback
函数的代码示例中使用了它。
我不确定如何在我的情况下利用这一点。这是我的代码(为简单起见,已删除)
主要流程是这样的:一个问题发生了变化,它称之为回调,questionChangeSystemCallback
. 从那里它更新它的状态值。完成更新它的值后,它会检查是否需要做其他事情并actionExecuter
根据需要调用。
//注意,重要的部分实际上是 setState questionsData 回调中底部的 forEach 循环。
questionChangeSystemCallback(Q) {
// updates current state of questionsData, checks for action string, executes any actions
if (Q == null) {
console.log("questionChangeSystemCallback required field, question, is null");
}
let updatedQuestionData = this.getQuestionDataWithUpdatedValue(Q);
this.setState({ questionsData: updatedQuestionData }, () => {
// after state is set, check if there are additional actions needed based on the actionOptions
if (Q.props.actions) {
let { actions } = Q.props;
let qval = Q.state.value;
let commandString = actions[qval];
if (commandString) {
let actionsToDo = commandString.split('&');
actionsToDo.forEach((action) => {
this.actionExecuter(action);
});
}
}
});
}
actionExecuter
showTab
这样做...基本上只是一个使用 true 或 fall 元素调用的 switch 语句:
actionExecuter = (actionString) => {
let splitActionString = actionString.split('::');
if (splitActionString.length !== 2) {
//TODO: Throw error
}
switch (splitActionString[0]) {
case "ShowTab":
this.showTab(splitActionString[1], true);
break;
case "HideTab":
this.showTab(splitActionString[1], false);
break;
default:
console.log("Requested action '" + splitActionString[0] + "' not recognized");
}
}
showTab
看起来像这样,this.state.hiddenTabs
如果 toShow 为 true 则有效地将 tabName 添加到,如果为 false 则从 tabName 中删除this.state.hiddenTabs
...然后将其设置state.hiddenTabs
为新数组。
showTab(tabName, toShow) {
let newHiddenTabs = this.state.hiddenTabs.slice();
console.log("After copy: ", newHiddenTabs);
let cleanTabName = tabName.replace(/ /g, '');
if (toShow) {
// remove all instances from newHiddenTabs
while (newHiddenTabs.includes(cleanTabName)) {
let index = newHiddenTabs.indexOf(cleanTabName);
if (index > -1) {
newHiddenTabs.splice(index, 1);
}
}
console.log("After removal: ", newHiddenTabs);
} else {
// add tabName to newHiddenTabs
newHiddenTabs.push(cleanTabName);
console.log("After addition: ", newHiddenTabs);
}
console.log("Before setting state: ", newHiddenTabs);
this.setState({ hiddenTabs: newHiddenTabs }, ()=> {
console.log("STATE after setting state: ", this.state.hiddenTabs);
}
);
}
使用该控制台日志主机,我正在学习 1)这里的逻辑有效,2)如果我有多个“动作”,因此 showTab 被调用两次......只有来自 SECOND 调用的数据最终在状态。此外,渲染方法不会在之后被调用。
举个例子:
最初this.state.hiddenTabs = ["WaterQuality","FieldForm","EWI","EDI"]
,我在渲染函数的顶部添加了一个 console.log("RENDER")。我作为动作运行 aShowTab(EDI, true)
和 a ShowTab(EWI, false)
。
以下是输出:
After copy: (4) ["WaterQuality", "FieldForm", "EWI", "EDI"]
**(correct)**
After removal: (3) ["WaterQuality", "FieldForm", "EWI"]
**(correct)**
Before setting state: (3) ["WaterQuality", "FieldForm", "EWI"]
**(correct)**
After copy: (4) ["WaterQuality", "FieldForm", "EWI", "EDI"]
**(nope - same initial state as first time through)**
After addition: (5) ["WaterQuality", "FieldForm", "EWI", "EDI", "EWI"]
**(given it's input, correct, but overall wrong)**
Before setting state: (5) ["WaterQuality", "FieldForm", "EWI", "EDI", "EWI"]
**(given it's input, correct, but overall wrong)**
RENDER
**(why are we rendering now... and why only once)**
STATE after setting state: (5) ["WaterQuality", "FieldForm", "EWI", "EDI", "EWI"]
**(this is the (erroneous) value from the second time through)**
STATE after setting state: (5) ["WaterQuality", "FieldForm", "EWI", "EDI", "EWI"]
**(this is the (erroneous) value from the second time through)**
解决方案
您的setState
电话正在批量处理。根据您调用的位置setState
,React 将自动对它们进行批处理,render
并且仅在整个批处理完成后才执行 a 。
您的问题可能在这里:
let newHiddenTabs = this.state.hiddenTabs.slice();
当您有多个操作时,此函数会被多次调用并且react
是批处理setState
。由于尚未刷新的更新,当它再次执行此操作时,状态尚未更新!
我的建议:将其提取到另一个函数并使用另一个setState
签名,该签名接受一个带有prevState
和props
作为参数的函数。它看起来有点像这样:
showTab(tabName, toShow) {
const processTabs = (hiddenTabs) => {
let cleanTabName = tabName.replace(/ /g, '');
if (toShow) {
hiddenTabs = hiddenTabs.filter((tab) => tab !== cleanTabName)
} else {
hiddenTabs.push(cleanTabName)
}
return hiddenTabs;
}
this.setState((prevState, props) => ({ hiddenTabs: processTabs([...prevState.hiddenTabs])}), () => {
console.log("STATE after setting state: ", this.state.hiddenTabs);
})
}
编辑:对不起,在 D 之前不小心发送了不完整的答案:
推荐阅读
- tensorflow - 为什么我的 Anaconda TensorFlow 安装不起作用(在 Ubuntu 上的 PyCharm 中)?(退出代码 132(被信号 4:SIGILL 中断))
- r - 识别、提取和计数序列中的模式
- vba - 禁用 PowerPoint 中默认功能区中的按钮
- java - 来自 persistence.xml 的 Java Play 访问实体
- c# - C# Discord.net 将文件作为图像添加到嵌入
- apache-spark - 将 S3 中的文本文件读入 Spark df:UsupportedOperationException
- error-handling - 在我的页面上显示服务器问题的行信息
- c++ - 如何将向量整数相乘
- assembly - 下例中执行'add al,'3''指令后不应该设置AF(辅助标志)吗?
- python - 如何删除python字典中的特殊字符?