this.setState 不工作(我的状态是一个数字)

this.setState isn't working (my state is a number)

我遇到问题:this.setState({score: counter});由于某种原因,它没有更新。为什么?即使我做 this.setState({score: 5}) 或 score:"a string" 它仍然不起作用。我错过了什么吗?无论我做什么,状态都不会改变。我必须添加额外的描述,因为该网站不允许我 post 我的问题。

displayResultsHandler = () => {
    var counter = 0;
    for(let i = 0; i < this.state.correctAnswers.length; i++) {
      if(this.state.correctAnswers[i] === this.state.userAnswers[i]) {
        counter = counter+1;
      }
    }

this.setState({
  score: counter
});

console.log("counter: " + counter);
console.log("score: " + this.state.score); // For some reason, this is always zero

}

我在下面添加了我的完整代码。也许会有帮助。

import React, { Component } from 'react';
import './App.css';
import Title from './Title/Title';
import Question from './Question/Question';
import Aux from './hoc/Aux';
import SubmitButton from './SubmitButton/SubmitButton';

class App extends Component {
  state = {
    questionArray: [
      "What is 9+10",
      "How many goals did Ronaldo score against Spain in the World Cup 2018",
      "Who Stole Ronaldo's (CR7) greates ever goal?",
      "Which one of these players ruined the NBA",
      "Who is currently number 1 in the internet L rankings?"
  ],
    answerChoicesArray: [
      ["1", "19", "21", "90", "-1"],
      ["1", "3", "5", "0", "-1"],
      ["Pepe", "Messi", "Casillas", "Benzema", "Nani"],
      ["Allen Iverson", "Kevin Durant", "Steph Curry", "Lebron James", "Russel Westbrook"],
      ["Drake", "Pusha T", "Russel Westbrook", "Lil Xan", "Russ"]
    ],

    correctAnswers: ["21", "3", "Nani", "Kevin Durant", "Russ"],

    userAnswers: ["", "", "", "", ""],

    score: 0

  }

  updateUserAnswersHandler = (oldArray, index, value) => {
    const newArray = oldArray;
    newArray[index] = value;
    this.setState({
      userAnswers: newArray
    });
  }

  displayResultsHandler = () => {
    var counter = 0;
    for(let i = 0; i < this.state.correctAnswers.length; i++) {
      if(this.state.correctAnswers[i] === this.state.userAnswers[i]) {
        counter = counter+1;
      }
    }

    this.setState({
      score: counter
    });

    console.log("counter: " + counter);
    console.log("score: " + this.state.score); // For some reason, this is always zero

    if(this.state.score < 5) {
      alert("You're dumb asf. Please leave");
    } else {
      alert("Welcome to NASA");
    }
  }

  render() {
    // var userAnswers;
    // console.log(userAnswers); How do I pass this as a prop? this.userAnswers? nope. Therefore it has to be a state
    console.log("User Answers are: " + this.state.userAnswers);
    return (
      <div className="App">
        <div className="container">
          
            <Title/>
            <h2>Only the most genius of individuals will pass</h2>
            <hr/>
            <Question
              correctAnswers={this.state.correctAnswers}
              updateUserAnswersHandler={this.updateUserAnswersHandler}
              userAnswers={this.state.userAnswers}
              questionArray={this.state.questionArray}
              answerChoicesArray={this.state.answerChoicesArray} />
            <SubmitButton
              clicked = {this.displayResultsHandler} />
        </div>
      </div>
    );
  }
}

export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

this.setState 是一个异步函数。

试试这个 -

this.setState({
  score: counter
},function(){
  console.log(this.state.score)
})

状态更新是异步的。您对 setState 的调用只是对更新进行排队,不会使其立即发生。

您还使用了错误的 setState 重载(您并不孤单,很多人都这样做!)。当您根据现有状态设置新状态时,您不能使用只接受对象的版本。您必须使用回调版本。如果你想在完成后使用结果状态,你可以传递第二个函数,该函数将在状态更新完成时调用:

displayResultsHandler = () => {
    this.setState(
        // Updater
        prevState => {
            var counter = 0;
            for(let i = 0; i < prevState.correctAnswers.length; i++) {
              if(prevState.correctAnswers[i] === prevState.userAnswers[i]) {
                counter = counter+1;
              }
            }
            return {score: counter};
        },
        // Completion callback
        () => {
            console.log("score: " + this.state.score);
        }
    );
};

但是,文档中关于使用完成回调的说明是这样的:

Generally we recommend using componentDidUpdate() for such logic instead.

this page of the documentation, and in the setState API docs.

中已涵盖所有内容

作为旁注,一些高级 JavaScript 功能(解构和 shorthand 属性 符号)和一个平淡无奇的功能(增量运算符)可以使该代码有点更简洁:

displayResultsHandler = () => {
    this.setState(
        // Updater
        ({correctAnswers, userAnswers}) => {                  // *** Destructuring
            let score = 0;
            for (let i = 0; i < correctAnswers.length; i++) {
              if (correctAnswers[i] === userAnswers[i]) {
                ++score;                                      // *** Increment
              }
            }
            return {score};                                   // *** Shorthand property
        },
        // Completion callback
        () => {
            console.log("score: " + this.state.score);
        }
    );
};

有些人甚至可能会使用 reduce 而不是 for 循环;不过,我不相信可读性不会受到影响:

displayResultsHandler = () => {
    this.setState(
        // Updater
        ({correctAnswers, userAnswers}) => ({
            score: correctAnswers.reduce(
                (score, answer, index) =>
                    score + (answer === userAnswers[index] ? 1 : 0),
                0
            )
        }),
        // Completion callback
        () => {
            console.log("score: " + this.state.score);
        }
    );
};

(您甚至可以删除条件运算符并只使用 score + (answer === userAnswers[index]),因为 true 强制转换为 1false 强制转换为 0,但是。 ..)