Каков наилучший метод для изменения React State на основе State? - PullRequest
0 голосов
/ 29 января 2020

Я нахожусь в процессе создания приложения React, и я хочу иметь возможность установить состояние upperScoreBonus, как только все остальные оценки не являются неопределенными. Если сумма всех оценок превышает 63, добавьте бонус, в противном случае наберите только 0.

Если я застрял, функция applyUpperScoreBonus откладывается до следующего вызова функции roll , Я в недоумении от того, куда мне следует позвонить, чтобы применитьUpperScoreBonus.

Я знаю, что что-то упустил.

class Game extends Component {
  constructor(props) {
    super(props);
    this.state = {
      dice: Array.from({ length: NUM_DICE }),
      locked: Array(NUM_DICE).fill(false),
      rollsLeft: NUM_ROLLS,
      isRolling: false,
      scores: {
        ones: undefined,
        twos: undefined,
        threes: undefined,
        fours: undefined,
        fives: undefined,
        sixes: undefined,
        upperBonusScore: undefined
      }
    };
    this.roll = this.roll.bind(this);
    this.doScore = this.doScore.bind(this);
    this.applyUpperScoreBonus = this.applyUpperScoreBonus.bind(this);
  }

    doScore(rulename, ruleFn) {
    // evaluate this ruleFn with the dice and score this rulename
    // only allows an update to the score card if the vaule has not yet been set. 

    if (this.state.scores[rulename] === undefined) {
      this.setState(st => ({
        scores: { ...st.scores, [rulename]: ruleFn(this.state.dice)},
        rollsLeft: NUM_ROLLS,
        locked: Array(NUM_DICE).fill(false)
      }));

      this.applyUpperScoreBonus();
      this.roll();

    }
  }

  applyUpperScoreBonus() {

    const st = this.state.scores;
    const upperArrayScores = [st.ones, st.twos, st.threes, st.fours, st.fives, st.sixes];
    let totalUpperScore = 0; 

    upperArrayScores.forEach(idx => {
      if(idx !== undefined) {
        totalUpperScore += idx
      }
    })


    if(upperArrayScores.every(idx => idx !== undefined)) {
      //if the total is more than 63, apply bonus of 35 otherwise 0

       this.setState(st => ({
        scores: { ...st.scores, upperBonusScore: totalUpperScore >= 63 ? 35 : 0},
      }));

      } 

  }

1 Ответ

1 голос
/ 29 января 2020

Здесь this.applyUpperScoreBonus() вызывается после setState, поскольку setState({}) является асинхронным c, this.applyUpperScoreBonus() получает обновление состояния только при следующем doScore() вызове

Это ваш кодовый блок

if (this.state.scores[rulename] === undefined) {
      this.setState(st => ({
        scores: { ...st.scores, [rulename]: ruleFn(this.state.dice)},
        rollsLeft: NUM_ROLLS,
        locked: Array(NUM_DICE).fill(false)
      }));

      this.applyUpperScoreBonus();
      this.roll();

    }

Измените его на

if (this.state.scores[rulename] === undefined) {
          this.setState(st => ({
            scores: { ...st.scores, [rulename]: ruleFn(this.state.dice)},
            rollsLeft: NUM_ROLLS,
            locked: Array(NUM_DICE).fill(false)
          }),()=> this.applyUpperScoreBonus()); // update here

          this.roll();

        }

Здесь this.applyUpperScoreBonus() вызывается при обратном вызове setState(), поэтому функция получит обновленное значение состояния.

...