Javascript 为什么componentDidUpdate在一系列状态更新后只触发一次?(反应)
我正在编写一个科学计算器,并且正在努力能够单击上一次计算的答案(显示的是UI的“历史”部分)并将该答案粘贴到显示器中,就像用户已经逐个输入了该答案的每个数字一样。因此,如果用户以前的计算是200+5,“以前的计算”将是“200+5”,而“以前的答案”将是“205”。我希望用户能够单击“205”,并将其显示在计算器上,就像他们输入了和2,然后是0,然后是5一样。我想将每个数字作为一个单独的输入,这样他们就可以一次删除一个数字,而不只是将整个数字粘贴为一个输入 我试图实现这一点的方法是将之前的计算(保存在状态中的对象中)拆分为一个数组,循环遍历该数组中的每个数字,并对其调用addToDisplay函数。addToDisplay函数会更新显示,但更重要的是,它会触发允许我的componentDidUpdate函数运行的条件,这会将当前显示信息保存在一个名为“inputHistory”的数组中。因此,当我单击“205”以查看inputHistory时,我希望inputHistory包含三项:[2']、['2'、[0']和[2]['2','0','5'] 当我分别输入这三个数字时,这是可行的,但当我从上一次的计算中执行此操作时,inputHistory中只包含一项:['2','0','5'].我最近问了一个关于解构的问题,我想这可能就是问题所在,但我不明白为什么,如果这是问题所在,我每次输入一个数字时会得到正确的结果。我认为componentDidUpdate()并不是每次调用addToDisplay()都会触发出于某些原因,我在管理状态的异步更新时也非常小心,但可能有什么东西从裂缝中漏掉了 以下是相关代码:Javascript 为什么componentDidUpdate在一系列状态更新后只触发一次?(反应),javascript,reactjs,Javascript,Reactjs,我正在编写一个科学计算器,并且正在努力能够单击上一次计算的答案(显示的是UI的“历史”部分)并将该答案粘贴到显示器中,就像用户已经逐个输入了该答案的每个数字一样。因此,如果用户以前的计算是200+5,“以前的计算”将是“200+5”,而“以前的答案”将是“205”。我希望用户能够单击“205”,并将其显示在计算器上,就像他们输入了和2,然后是0,然后是5一样。我想将每个数字作为一个单独的输入,这样他们就可以一次删除一个数字,而不只是将整个数字粘贴为一个输入 我试图实现这一点的方法是将之前的计算(
addToDisplay(input, parensNeeded, spanNeeded, exp) {
this.setState((prevState) => {
let calcArr = prevState.newCalc ? [] : [...prevState.currentMath], finalInput
// deal with any changes in exponent
if (prevState.lastInput=== `<span class='invisible'>^</span><span class='exp-${this.state.exponentCount}'>□`) {
calcArr.pop();
finalInput = `<span class='invisible'>^</span><span class='exp-${this.state.exponentCount}'>${input}`
} else {
finalInput = input
}
//handle a minus becoming a negative sign
if (prevState.lastInput === ' - ' && /[×\-÷\+]/.test(prevState.currentMath[prevState.currentMath.length-2])) {
calcArr[calcArr.length-1] = ' -'
}
//add the new input to the array
calcArr.push(finalInput)
//add/update spans to keep stylings intact
let counter = prevState.exponentCount;
let spans = '';
while (counter > 0) {
spans = spans + '</span>';
counter--;
};
//add new parens, if needed
let styledParens = `<span class='parens exp-${this.state.exponentCount}'>)</span>`;
return {
currentMath : calcArr,
calcActive : true,
lastInput : input,
inverse : false,
newCalc : false,
exponentCount : exp === '+'
? prevState.exponentCount + 1
: exp === '-'
? prevState.exponentCount - 1
: prevState.exponentCount,
spanStr : spanNeeded === 'yes' ? spans : prevState.spanStr,
rightParensArr : parensNeeded === 'yes'
? [styledParens, ...prevState.rightParensArr]
: input === ')' | input === '</span>)'
? prevState.rightParensArr.length > 1
? prevState.rightParensArr.slice(1)
: []
: [...prevState.rightParensArr],
inputHistUpdated : false
}
});
}
无论如何,如果有人能看到我遗漏的东西,请随意指出。谢谢!我必须指出,事实上你正在以一种非常奇怪的方式使用setState。计算下一个状态应该是什么,然后设置它。如果你甚至可以,不要做你正在做的事情。在调用setStat之前先进行所有的计算e、 并且只向setState传递您想要的状态更新。谢谢您的评论。我根据您和文档所说的清理了代码,但这仍然没有解决我的问题。事实上,这一切都被包装在一个事件中,把一切都搞砸了吗?您的帖子仍然显示在
setState
中计算新状态的代码,而不是c首先计算它,然后调用this.setState(newState)
。还要注意,您在goToAns
中设置状态,然后在回调函数中再次设置状态:设置的状态太多了。请先完成工作,然后作为最后一步,更新组件状态,使其能够重新加载自身。不要使用中间状态设置:根据定义,中间结果不是真实状态。最后一点:如果您在componentdiddupdate
中使用基于先前状态的setState
,则会出现问题。请务必基于更改的道具更新状态,但决不要基于状态更改触发的函数中的状态更新状态。这只是做了错误的反应,因此重新获取该结果是非常值得的ct教程(即使你已经这样做了)来(重新)熟悉你应该如何在React中编写代码,思考数据和更新。啊,我明白了。这很有意义。我一定会回到基础上来,更新我的理解。谢谢你的帮助!我感谢你抽出时间。
goToAns(e, answer) {
e.preventDefault();
this.setState({
rightParensArr : [],
calActive: true,
currentMath : [],
spanStr : [],
exponentCount : 0,
lastInput : '',
historyVisible : false,
newCalc : false,
inputHistory : []
}, () => {
let ansArr = answer.split('');
let i = 0;
while (i < ansArr.length) {
this.addToDisplay(ansArr[i]);
i++;
}
})
}
if (!this.state.inputHistUpdated) {
let newInputHist = {
currentMath : [...this.state.currentMath],
exponentCount : this.state.exponentCount,
spanStr : this.state.spanStr,
lastInput : this.state.lastInput,
rightParensArr : [...this.state.rightParensArr],
}
this.setState((prevState) => {
return {
inputHistory : [newInputHist, ...prevState.inputHistory],
inputHistUpdated : true
}
})
}