首页 > 解决方案 > React 应用程序没有正确更新 this.state

问题描述

我目前正在努力获得我的全栈,并决定扩展我对 JavaScript 的了解。这个决定最终把我带到了 React,但我 - 如前所述 - 这个库中的菜鸟。但这仅意味着我必须更多地使用这项技术才能在上述知识方面取得进步。

乍一看,我正在处理的实际问题似乎非常简单。显然我的反应应用程序没有正确更新 this.state 。我知道 React 中的 setState 方法是异步的,因此当触发 setState() 的内置第二个回调时,我会触发其他自定义方法。这种技术显然不是最好的,因为它根本没有按计划工作。

我的应用程序是关于一个带有基本数学运算符的简单计算器。我想实现一个功能,在“输入”下实时跟踪给定表达式的潜在结果,但我的方法不起作用,尽管我认为它离真正的解决方案并不太远。正确的函数在正确的时间被触发,但是 this.state.result 和 this.state.resultExpression 显然都没有,因为它们没有出现在它们的渲染框中。我的 updateDigit() 函数按计划工作,但是在点击“等于”按钮后显示结果时,实际上什么都没有显示——甚至整个输入的输入都消失了。

这是我的代码:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './calc.css';

const showHistory = false;
const decimalPlace = 3;

const operatorSet = ["+", "-", '*', '/', '%'];

class Calculator extends Component {

    constructor(props) {
        super(props);
        this.recentResult == false;
        this.state = {
            output: '0',
            preview: '',
            history: [],
            result: '',
            resultExpression: ''
        };
        this.updateDigit = this.updateDigit.bind(this);
        this.updatePreview = this.updatePreview.bind(this);
        this.clearOutput = this.clearOutput.bind(this);
        this.getResult = this.getResult.bind(this);
        this.showResult = this.showResult.bind(this);
    }

    render() {
        return (
            <div className="calculator">
                <div className="comp5">
                    <div className="output">{this.state.output}</div>
                    <div className="preview">{this.state.getResult}</div>
                </div>
                <div className="comp4">
                    <div className="topbtn"><a href="#" draggable="false" onClick={this.updateDigit}>(</a></div>
                    <div className="topbtn"><a href="#" draggable="false" onClick={this.updateDigit}>)</a></div>
                    <div className="topbtn"><a href="#" draggable="false" onClick={this.updateDigit}>%</a></div>
                    <div className="button_div button_control">
                        <a href="#" draggable="false" onClick={this.updateDigit}>/</a>
                    </div>
                </div>
                <div className="comp3">
                    <div className="numpad"><a href="#" draggable="false" onClick={this.updateDigit}>7</a></div>
                    <div className="numpad"><a href="#" draggable="false" onClick={this.updateDigit}>8</a></div>
                    <div className="numpad npl"><a href="#" draggable="false" onClick={this.updateDigit}>9</a></div>
                    <div className="button_min button_control">
                        <a href="#" draggable="false" onClick={this.updateDigit}>*</a>
                    </div>
                </div>
                <div className="comp2">
                    <div className="numpad"><a href="#" draggable="false" onClick={this.updateDigit}>4</a></div>
                    <div className="numpad"><a href="#" draggable="false" onClick={this.updateDigit}>5</a></div>
                    <div className="numpad npl"><a href="#" draggable="false" onClick={this.updateDigit}>6</a></div>
                    <div className="button_plus button_control">
                        <a href="#" draggable="false" onClick={this.updateDigit}>-</a>
                    </div>
                </div>
                <div className="comp1">
                    <div className="numpad"><a href="#" draggable="false" onClick={this.updateDigit}>1</a></div>
                    <div className="numpad"><a href="#" draggable="false" onClick={this.updateDigit}>2</a></div>
                    <div className="numpad npl"><a href="#" draggable="false" onClick={this.updateDigit}>3</a></div>
                    <div className="button_plus button_control">
                        <a href="#" draggable="false" onClick={this.updateDigit}>+</a>
                    </div>
                </div>
                <div className="comp0">
                    <div className="numpad clear"><a href="#" draggable="false" onClick={this.clearOutput}>C</a></div>
                    <div className="numpad"><a href="#" draggable="false" onClick={this.updateDigit}>0</a></div>
                    <div className="numpad npl"><a href="#" draggable="false" onClick={this.updateDigit}>.</a></div>
                    <div className="button_res button_control">
                        <a href="#" draggable="false" onClick={this.showResult}>=</a>
                    </div>
                </div>
                <History expressions={this.state.history} />
            </div>
        );
    }


    updateDigit(event) {
        event.preventDefault;
        if (this.recentResult == true || this.state.output == "0") {
            this.recentResult = false;
            this.setState({ output: '' });
        }
        const newDigit = {
            digit: event.target.innerHTML,
            id: Date.now()
        };
        this.setState(prevState => ({
            output: prevState.output.concat(newDigit.digit)
        }), this.updatePreview());
    }


    updatePreview(event) {
        if (this.state.output == "0") {
            this.setState({ preview: '' });
        }
        let checkPreviewable = (output) => {
            var charactersAfterOperator = false;
            for (var i = 0; i < operatorSet.length; i++) {
                var currentOperator = operatorSet[i];
                let operatorLocation = output.indexOf(currentOperator)
                if (operatorLocation < output.length && operatorLocation > 0) {
                    return true;
                } else {
                    return false;
                }
            }
        };
        let previewable = checkPreviewable(this.state.output);
        if (previewable === true) {
            let resultExpression = this.state.resultExpression;
            this.setState({ preview: this.state.result });
        } else {
            this.setState({ preview: '' });
        }
    }


    clearOutput(event) {
        event.preventDefault();
        this.setState({ output: '0' });
    }


    getResult(event) {
        var result = eval(this.state.output).toFixed(decimalPlace);
        var resultExpression = this.state.output + "=" + result;

        this.setState({
            result: result,
            resultExpression: resultExpression
        }, this.updatePreview());
    }


    showResult(event) {
        this.getResult();
        let result = this.state.result;
        let resultExpression = this.state.resultExpression;
        this.setState({ output: result });
        this.setState(prevState => ({
            history: prevState.history.concat(resultExpression)
        }));
        this.recentResult = true;
    }

}

export default Calculator;



class History extends React.Component {
    render() {
        if (showHistory === false) return false;
        return (
            <ul>
                {this.props.expressions.map(expression => (
                    <li>{expression}</li>
                ))}
            </ul>
        )
    }
}

您是否知道为什么会发生这种情况,您是否真的经历过类似的情况,或者您甚至可以提供替代/解决方案吗?

提前感谢您的各种帮助,J0nny

标签: javascriptreactjsfrontendweb-frontend

解决方案


我在看你的代码,我可以看到你有很多 setState 函数。

每次调用 setstate 时,您的组件都会再次呈现,并且您的代码不会完成当前流程。

如果需要在 setstate 函数之后执行任何操作,是否需要设置 next 函数作为 setstate 函数的回调,例如:

this.setState({value:1}, callBack)

我希望这对您有所帮助如果您愿意,我们可以在出现或其他事情上进行交谈,我可以更好地向您解释。


推荐阅读