Приложение React не обновляет this.state должным образом

В настоящее время я много работаю над полным стеком и решил расширить свои знания о JavaScript. Это решение в конечном итоге привело меня к React, но я, как уже упоминалось, новичок в этой библиотеке. Но это означает только то, что мне нужно больше работать с этой технологией, чтобы развиваться с точки зрения упомянутых знаний.

Актуальные проблемы, с которыми я сталкиваюсь, на первый взгляд кажутся очень простыми; По-видимому, мое приложение для реагирования не обновляет this.state должным образом. Я осведомлен о том, что метод setState в React является асинхронным, поэтому я запускаю другие пользовательские методы, когда запускается встроенный второй обратный вызов 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


person J0nny    schedule 24.04.2018    source источник


Ответы (1)


Я следил за вашим кодом и вижу, что у вас много функций setState.

Каждый раз, когда вы вызываете setstate, ваш компонент снова отображается, а ваш код не завершает текущий поток.

Если вам нужно выполнить что-либо после функции setstate, нужно ли вам установить следующую функцию как обратный вызов функции setstate, например:

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

Я надеюсь, что это поможет. Если вы хотите, мы можем поговорить о чем-то другом, и я смогу вам лучше объяснить.

person Nicolas Takashi    schedule 24.04.2018
comment
Нет, это вообще не работает, чтобы вывести какой-либо результат. Это работает в вашей настройке? - person J0nny; 24.04.2018
comment
Извините, @ J0nny, я исправил свой ответ. Вам нужно будет внести некоторые изменения в свой код, если вы хотите, чтобы мы могли поговорить с помощью внешнего или другого голосового чата, чтобы лучше объяснить. Если вы не поняли мой новый ответ, дайте мне знать, я постараюсь вам помочь. - person Nicolas Takashi; 24.04.2018
comment
Я не знал, что все снова отображается после вызова setState () ... спасибо за эту деталь. Знаете ли вы, как тогда я смогу вызвать последующие методы setState () для моего кода? - person J0nny; 24.04.2018
comment
@ J0nny, если вам нужно выполнить какой-то код после функции this.setState, вам нужно передать другую функцию в качестве обратного вызова, например: this.setState({value:1}, callBack) Но в вашем текущем cenario я думаю, что вам нужно внести некоторые изменения в свой код, попробуйте уменьшить количество этого. setstate вызов. - person Nicolas Takashi; 24.04.2018
comment
Я понял, о чем вы говорите, но где логика вложения вызовов setState в отдельные методы и их отдельного вызова? Компоненты, по-видимому, все равно отрисовываются снова ... Что вы имеете в виду под уменьшением количества this.setstate? Не могли бы вы более подробно рассказать о своих проблемах и способах их реализации? Спасибо за быстрые ответы! - person J0nny; 24.04.2018
comment
@ J0nny Извини, я постараюсь быть более конкретным, я попробую создать какой-нибудь git.gist с небольшим количеством кода. Если вы хотите, чтобы мы могли заниматься парным программированием, о чем вы думаете? - person Nicolas Takashi; 24.04.2018
comment
Спасибо за предложение, но в настоящее время меня не интересует какое-либо программирование или голосовой чат. Я надеялся, что вы сможете предоставить решения в этой форме комментариев или ответов. Извините за поздний ответ ... напряженный день - person J0nny; 25.04.2018
comment
Буду рад снова увидеть, как ты мне помогаешь @NicolasTakashi - person J0nny; 27.04.2018
comment
Извините за задержку @ J0nny Я попробую создать что-нибудь сегодня, моя неделя была сложной. - person Nicolas Takashi; 27.04.2018