我从另外一百万个问题中看到,在调用setState之后可以使用回调。实际上,我在questionChangeSystemCallback
函数的代码示例中使用了它。
我不确定在我的情况下如何利用这一点。这是我的代码(为简单起见而被剥离)
主要流程是这样的:一个问题改变了,它称为回调questionChangeSystemCallback
。从那里更新状态的价值。完成值的更新后,它会检查其他事情并根据需要调用actionExecuter
。
//请注意,最重要的部分实际上是setStatequestsData回调中底部的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
执行此操作...基本上只是一个switch语句,用于使用true或fall元素调用showTab
:
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
如下所示,如果toShow为true,则将tabName有效地添加到this.state.hiddenTabs
;如果为false,则将其从this.state.hiddenTabs
中删除tabName,然后将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被调用了两次...仅第二次调用中的数据结束状态。此外,render方法不会在以后被调用。
例如:
初始this.state.hiddenTabs = ["WaterQuality","FieldForm","EWI","EDI"]
我已经在我的渲染函数的顶部添加了console.log(“ RENDER”)。
我将ShowTab(EDI, true)
和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)**
答案 0 :(得分:3)
您的setState
呼叫正在批量处理。整个批处理完成后,具体取决于您要呼叫setState
,React will batch them automatically并仅执行render
的位置。
您所遇到的问题可能在这里:
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之前意外发送的答案不完整: