Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么componentDidUpdate在一系列状态更新后只触发一次?(反应)_Javascript_Reactjs - Fatal编程技术网

Javascript 为什么componentDidUpdate在一系列状态更新后只触发一次?(反应)

Javascript 为什么componentDidUpdate在一系列状态更新后只触发一次?(反应),javascript,reactjs,Javascript,Reactjs,我正在编写一个科学计算器,并且正在努力能够单击上一次计算的答案(显示的是UI的“历史”部分)并将该答案粘贴到显示器中,就像用户已经逐个输入了该答案的每个数字一样。因此,如果用户以前的计算是200+5,“以前的计算”将是“200+5”,而“以前的答案”将是“205”。我希望用户能够单击“205”,并将其显示在计算器上,就像他们输入了和2,然后是0,然后是5一样。我想将每个数字作为一个单独的输入,这样他们就可以一次删除一个数字,而不只是将整个数字粘贴为一个输入 我试图实现这一点的方法是将之前的计算(

我正在编写一个科学计算器,并且正在努力能够单击上一次计算的答案(显示的是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()都会触发出于某些原因,我在管理状态的异步更新时也非常小心,但可能有什么东西从裂缝中漏掉了

以下是相关代码:

 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 === ' - ' && /[&times;\-÷\+]/.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
            }
        })

    }