@sergemin

Как работать со state в React?

Уже задавал похожий вопрос, но понимания не пришло. Пишу калькулятор и возникает проблема с тем, что стейт обновляется с запозданием в шаг. Подскажите, в чем проблема. Вывожу все данные стейта в консоль, но при этом в консоли отображается все с запозданием в шаг.
function Button(props) {
    return (
        <button onClick={props.onClick}>
            {props.value}
        </button>
    )
}
function Input(props) {
    return (
        <input type="text" value={props.value}/>
    )
}
export default class App extends React.Component {
    constructor() {
        super();
        this.state = {
            valueInput: 0,
            firstOperand: '',
            secondOperand: '',
            operator: '',
            result: '',
        }
        this.renderButton = this.renderButton.bind(this);
        this.refreshInput = this.refreshInput.bind(this);
    }
    refreshInput(event) {
        const target = event.target.innerHTML;
        // if result exists
        if(this.state.result) {
            let reset = '',
                first = target;
            this.setState({
                valueInput:first,
                firstOperand: first,
                secondOperand: reset,
                result: reset,
                operator: reset,
            })
        }
        //if you clicked a number
        if(!isNaN(parseFloat(target)) && isFinite(target)) {
            if(this.state.result) {
                let first = target,
                    reset = '';
                this.setState({
                    firstOperand: first,
                    secondOperand: reset,
                    operator: reset,
                    result: reset,
                })
            }
            if(!this.state.secondOperand && !this.state.operator) {
                let number = parseFloat(this.state.firstOperand + target);
                this.setState({
                    firstOperand: number,
                    valueInput: number,
                })
            } else {
                let number = parseFloat(this.state.secondOperand + target);
                this.setState({
                    secondOperand: number,
                    valueInput: number,
                })
            }

        }
        //if you clicked a point
        if(target === '.') {
            if(!this.state.firstOperand) {
                let number = '0.';
                this.setState({
                    firstOperand: number,
                    valueInput: number
                })
                //is integer
            } else if (this.state.firstOperand && (this.state.firstOperand ^ 0) === this.state.firstOperand) {
                let result = this.state.firstOperand + '.';
                this.setState({
                    firstOperand: result,
                    valueInput: result,
                })
            }
             if (this.state.secondOperand && (this.state.secondOperand ^ 0) === this.state.secondOperand) {
                let result = this.state.secondOperand + '.';
                this.setState({
                    secondOperand: result,
                    valueInput: result,
                })
            }
        }
        //if you clicked an operator
        if(target === '*' || target === '/' || target === '+' || target === '-') {
            if(!this.state.firstOperand) {
                alert('Please, state 1st operand');
            } else {
                let operatorType = target;
                this.setState({
                    valueInput: operatorType,
                    operator: operatorType,
                });
            }
            if(this.state.result) {
                let first = this.state.result,
                    operator = target,
                    reset = '';
                this.setState({
                    firstOperand: first,
                    operator: operator,
                    secondOperand:  reset,
                    result: reset,
                    })
            }
        }
        //if you clicked C button
        if(target === 'C') {
            if(!this.state.firstOperand && !this.state.secondOperand) {
                const result = 0;
                this.setState({
                    result: result,
                    valueInput: result,
                })
            } else if(this.state.firstOperand && !this.state.secondOperand) {
                let first = this.state.firstOperand +'';
                let result = first.substring(0, first.length-1);
                this.setState({
                    firstOperand: result,
                    valueInput: result,
                })
            }
        }

        //if you clicked an equal
        if(target === '=' && this.state.firstOperand && this.state.secondOperand) {
            let mainResult = 0,
                fixedResult;
            switch(this.state.operator) {
                case '*':
                    mainResult=parseFloat(this.state.firstOperand)*parseFloat(this.state.secondOperand);
                    break;
                case '/':
                    mainResult=parseFloat(this.state.firstOperand)/parseFloat(this.state.secondOperand);
                    break;
                case '+':
                    mainResult=parseFloat(this.state.firstOperand)+parseFloat(this.state.secondOperand);
                    break;
                case '-':
                    mainResult=parseFloat(this.state.firstOperand)-parseFloat(this.state.secondOperand);
                    break;
                default: alert('Unknown result');
            }
            fixedResult = mainResult.toFixed(2);
            this.setState({
                result: fixedResult,
                valueInput: fixedResult,
            })
        }
        console.log('result: '+this.state.result,
        'first: ' + this.state.firstOperand,
        'second: ' + this.state.secondOperand,
        'operator: ' + this.state.operator);
    }
    renderButton(name) {
        return (
            <Button className='button_calculator'
                    value={name}
                    onClick={this.refreshInput}
            />
        )
    }
    render() {
        return (
            <div className="calculator">
                <div className="row">
                    <Input value={this.state.valueInput}/>
                </div>
                <div className="row">
                    {this.renderButton(1)}
                    {this.renderButton(2)}
                    {this.renderButton(3)}
                    {this.renderButton('*')}
                </div>
                <div className="row">
                    {this.renderButton(4)}
                    {this.renderButton(5)}
                    {this.renderButton(6)}
                    {this.renderButton('/')}
                </div>
                <div className="row">
                    {this.renderButton(7)}
                    {this.renderButton(8)}
                    {this.renderButton(9)}
                    {this.renderButton('+')}
                </div>
                <div className="row">
                    {this.renderButton('C')}
                    {this.renderButton(0)}
                    {this.renderButton('.')}
                    {this.renderButton('-')}
                </div>
                <div className="row">
                    {this.renderButton('=')}
                </div>
            </div>
        )
    }
}
  • Вопрос задан
  • 345 просмотров
Решения вопроса 1
Hardwit
@Hardwit
Front-end Developer
Дело в том, что setState выполняется не мгновенно в целях оптимизации. Если нужно вывести или зайдействовать стейт после обновления, тогда нужно делать это в колбэке у сетСтэйта.
Вот пример такого же вопроса: stackoverflow
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы