Создание приложения калькулятора в React. setState не работает

#reactjs #state

#reactjs #состояние

Вопрос:

Я создаю приложение-калькулятор в React. Здесь у меня есть компонент приложения и компонент кнопки. Когда я нажимаю кнопку, несмотря на то, что я устанавливаю значение параметра (event.target.getAttribute(‘data-number’), консоль регистрирует число, отличное от атрибута кнопки.

Когда я нажимаю кнопку с «data-number = 1», состояние «результат» устанавливается на «0». Затем я нажимаю кнопку с «data-number = 7», состояние «результат» устанавливается на «1». Интересно, что происходит и как исправить эту проблему.

 class App extends React.Component {
    state = { result: 0 };

    currentNumber = (number) => {
        this.setState({ result: number })
        console.log("Number from Button", number); // 1
        console.log("Current number in state", this.state.result); // 0
    }

    render() {
        return (
            <div>
                <Button onClick = {this.currentNumber} />
            </div>
        );
    }
}
  
 class Button extends React.Component {

    render() {
        return (
            <ul>
                <li><button data-number="1" onClick={event => this.props.onClick(event.target.getAttribute('data-number'))}>1</button></li>
            </ul>

  

Комментарии:

1. Извините, я просто вырезал остальную часть своего кода в компоненте Button. Это должно быть <li><кнопка data-number=»1″ onClick={событие => this.props.onClick(event.target.getAttribute(‘data-number’))}>1</button></li>, <li>=»2″ onClick={событие => this.props.onClick(event.target.getAttribute(‘data-number’))}>2</button></li>, … <li><кнопка data-number=»7″ onClick={событие =>this.props.onClick(event.target.getAttribute(‘data-number’))}>7</button></li>

2. можете ли вы добавить этот код в текст вашего вопроса для ясности?

Ответ №1:

Вызов setState является асинхронным, что означает, что состояние не обновляется сразу. Вы можете передать обратный вызов, который запускается после обновления состояния:

 this.setState({ result: number }, () => {
        console.log("Number from Button", number); // 1
        console.log("Current number in state", this.state.result); // 1
})
  

Комментарии:

1. Спасибо! Я не уверен, правильно ли я понимаю, но я прочитаю документ подробнее..

Ответ №2:

Как упоминал @Smarticles101, setState является асинхронным. Вот ваш код, работающий правильно.

Обратите внимание на разницу между журналами обратного вызова и внешними журналами обратного вызова. Проверьте эти документы в setState для получения дополнительной информации.

 class App extends React.Component {
    state = { result: 0 };

    currentNumber = (number) => {
        this.setState({ result: number }, () => {
          console.log("Callback, number: ", number);
          console.log("Callback, result: ", this.state.result);
        })
        
        console.log("Outside callback, number: ", number);
        console.log("Outside callback, result: ", this.state.result);
        
    }

    render() {
        return (
            <div>
                <Button onClick={this.currentNumber} />
            </div>
        );
    }
}

class Button extends React.Component {

    render() {
        return (
            <ul>
            <li><button data-number="1" onClick={event => this.props.onClick(event.target.getAttribute('data-number'))}>1</button></li>,
            <li><button data-number="2" onClick={event => this.props.onClick(event.target.getAttribute('data-number'))}>2</button></li>, ...
            <li><button data-number="7" onClick={event => this.props.onClick(event.target.getAttribute('data-number'))}>7</button></li>
            </ul>
            )
    }
}

ReactDOM.render((<App/>), document.getElementById('testing'));  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="testing" />  

Комментарии:

1. Спасибо! Я все еще не понимаю асинхронную часть, но я буду искать дальше..