2016-12-08 4 views
2

Я создаю очень примитивное приложение для викторины с ReactJS, и у меня возникли проблемы с обновлением состояния моего компонента Questions. Его поведение он делает правильный индекс questions массива в DOM несмотря this.state.questionNumber всегда быть на один шаг позади в handleContinue():ReactJS onClick state change one step behind

import React from "react" 

export default class Questions extends React.Component { 
    constructor() { 
    super() 
    this.state = { 
     questionNumber: 1 
    } 
    } 

    //when Continue button is clicked 
    handleContinue() { 
    if (this.state.questionNumber > 3) { 
     this.props.unMount() 
    } else { 
     this.setState({ 
     questionNumber: this.state.questionNumber + 1 
     }) 
     this.props.changeHeader("Question " + this.state.questionNumber) 
    } 
    } 

    render() { 
    const questions = ["blargh?", "blah blah blah?", "how many dogs?"] 
    return (
     <div class="container-fluid text-center"> 
     <h1>{questions[this.state.questionNumber - 1]}</h1> 
     <button type="button" class="btn btn-primary" onClick={this.handleContinue.bind(this)}>Continue</button> 
     </div> 
    ) 
    } 
} 
+1

Я не уверен, что я понимаю ваш вопрос. Я вижу, что вы получаете доступ к 'this.state.questionNumber' сразу после того, как вы поставили в очередь обновление для него. Установка состояния в React - это асинхронная операция, поэтому нет гарантии, что она будет обновляться во времени для следующего вызова функции. От официального документа: _setState() не сразу мутирует this.state, но создает ожидающий переход состояния. Доступ к this.state после вызова этого метода может потенциально вернуть существующее значение. –

+0

Что было бы хорошей альтернативой в этом случае? –

ответ

10

setState() является not necessarily a synchronous operation:

setState() не сразу мутировать this.state, но и создает ожидающий переход состояния. Доступ this.state aft

Нет гарантии синхронной работы вызовов setState, и звонки могут быть отправлены для повышения производительности.

По этой причине this.state.questionNumber еще может удерживать предыдущее значение здесь:

this.props.changeHeader("Question " + this.state.questionNumber) 

Вместо использовать callback function которая вызывается переходного состояния полной:

this.setState({ 
    questionNumber: this.state.questionNumber + 1 
},() => { 
    this.props.changeHeader("Question " + this.state.questionNumber) 
}) 
+1

Мне очень нравится это решение функции обратного вызова –

1

Как говорит Сэндвич, если вы получаете доступ к правильному состоянию на корме используя setState, у вас нет гарантии фактического значения. Вы могли бы сделать что-то вроде этого:

handleContinue() { 
    if (this.state.questionNumber > 3) { 
    this.props.unMount() 
    } else { 
    const newQuestionNumber = this.state.questionNumber + 1 
    this.setState({ 
     questionNumber: newQuestionNumber 
    }) 
    this.props.changeHeader("Question " + newQuestionNumber) 
    } 
}