【问题标题】:React Application not updating this.state properlyReact 应用程序没有正确更新 this.state
【发布时间】:2018-04-24 19:23:12
【问题描述】:

我目前正在努力获得我的全栈,并决定扩展我对 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

【问题讨论】:

    标签: javascript reactjs frontend web-frontend


    【解决方案1】:

    我在看你的代码,我发现你有很多 setState 函数。

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

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

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

    我希望这会有所帮助 如果您愿意,我们可以面谈或其他事情,我可以更好地向您解释。

    【讨论】:

    • 不,渲染任何结果都不起作用。它在您的设置中有效吗?
    • 对不起@J0nny 我修正了我的答案,如果您希望我们可以通过出现或其他语音聊天进行交谈,您需要对您的代码进行一些更改,以便更好地解释。如果您不理解我的新答案,请告诉我,我会尽力帮助您。
    • 我不知道调用 setState() 后一切都重新渲染了……谢谢你提供的细节。你知道吗,那我怎样才能为我的代码调用后续的 setState() 方法?
    • @J0nny 如果你需要在this.setState 函数之后执行一些代码,你需要传递另一个函数作为回调,例如:this.setState({value:1}, callBack) 但在你当前的情况下,我认为你需要做一些改变在您的代码中,尽量减少 this.setstate 调用的数量。
    • 我确实明白你在说什么,但是将 setState 调用嵌套在各个方法中并单独调用它们的逻辑在哪里?无论如何,组件显然又被渲染了......“减少 this.setstate 的数量”是什么意思?您能否更明确地说明您的担忧以及如何实现它们,好吗?感谢您的快速回复!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-21
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多