如何使用 componentDidMount 重置状态?

How to reset state with componentDidMount?

我是 React 的新手,我正在做一个测验。我现在想做的是在您遇到新问题时将类名重置为初始状态。我想我想使用 componentDidUpdate 但不确定它是如何工作的。

  componentDidUpdate() {
    this.setState({
      classNames: ["", "", "", ""]
    });
  }

这里是完整的组件代码:

class Answers extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isAnswered: false,
      classNames: ["", "", "", ""]
    };

    this.checkAnswer = this.checkAnswer.bind(this);
  }

  checkAnswer(e) {
    let { isAnswered } = this.props;

    if (!isAnswered) {
      let elem = e.currentTarget;
      let { correct, increaseScore } = this.props;
      let answer = Number(elem.dataset.id);
      let updatedClassNames = this.state.classNames;

      if (answer === correct) {
        updatedClassNames[answer - 1] = "right";
        increaseScore();
      } else {
        updatedClassNames[answer - 1] = "wrong";
      }

      this.setState({
        classNames: updatedClassNames
      });

      this.props.showButton();
    }
  }

  componentDidUpdate() {
    this.setState({
      classNames: ["", "", "", ""]
    });
  }

  render() {
    let { answers } = this.props;
    let { classNames } = this.state;

    return (
      <div id="answers">
        <ul>
          <li onClick={this.checkAnswer} className={classNames[0]} data-id="1">
            <p>{answers[0]}</p>
          </li>
          <li onClick={this.checkAnswer} className={classNames[1]} data-id="2">
            <p>{answers[1]}</p>
          </li>
          <li onClick={this.checkAnswer} className={classNames[2]} data-id="3">
            <p>{answers[2]}</p>
          </li>
          <li onClick={this.checkAnswer} className={classNames[3]} data-id="4">
            <p>{answers[3]}</p>
          </li>
        </ul>
      </div>
    );
  }
}

export default Answers;

感谢任何帮助!自从我学习以来,对整个代码项目的反馈也非常感谢。

下面是一个link完整的项目:

https://codesandbox.io/s/another-quiz-mfmop

问题是,如果您在 componentDidUpdate 中更改状态,它将立即触发另一次更新,因此会再次 运行 componentDidUpdate 并导致无限循环。所以你应该把 setState 移到别处,或者把它放在一个条件后面。例如:

componentDidUpdate() {
  if (!this.state.classNames.every(className => className === "") { // Check if there is an item in the array which doesn't match an empty string ("")
    this.setState({ // Only update state if it's necessary
      classNames: ["", "", "", ""]
    });
  }
}

您可以找到更新的 CodeSandbox here

首先,您必须添加一个按钮来重置 类 名称,此按钮将调用一个函数来重置它们,例如:


import React from "react";

class Answers extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isAnswered: false,
      classNames: ["", "", "", ""]
    };
  }

  checkAnswer = e => {
    let { isAnswered } = this.props;

    if (!isAnswered) {
      let elem = e.currentTarget;
      let { correct, increaseScore } = this.props;
      let answer = Number(elem.dataset.id);
      let updatedClassNames = this.state.classNames;

      if (answer === correct) {
        updatedClassNames[answer - 1] = "right";
        increaseScore();
      } else {
        updatedClassNames[answer - 1] = "wrong";
      }

      this.setState({
        classNames: updatedClassNames
      });

      this.props.showButton();
    }
  };

  reset = () => {
    this.setState({
      isAnswered: false,
      classNames: ["", "", "", ""]
    });
  };
  render() {
    let { answers } = this.props;
    let { classNames } = this.state;

    return (
      <div id="answers">
        <button onClick={this.reset}>RESET</button>
        <ul>
          <li onClick={this.checkAnswer} className={classNames[0]} data-id="1">
            <p>{answers[0]}</p>
          </li>
          <li onClick={this.checkAnswer} className={classNames[1]} data-id="2">
            <p>{answers[1]}</p>
          </li>
          <li onClick={this.checkAnswer} className={classNames[2]} data-id="3">
            <p>{answers[2]}</p>
          </li>
          <li onClick={this.checkAnswer} className={classNames[3]} data-id="4">
            <p>{answers[3]}</p>
          </li>
        </ul>
      </div>
    );
  }
}

export default Answers;

如果您更改 key 的答案,有一个简单的解决方法(并推荐作为 React 最佳实践),工作演示:https://codesandbox.io/s/another-quiz-wgycs

<Answers
  key={question}    // <-- oh hi
  answers={answers}
  correct={correct}
  ...

理想情况下,您会使用 id,并且由于大多数现代数据结构都有一个 ID,因此使用 key={question_id} 是理想的选择,因为密钥必须是唯一的:

{
    id: 1
    question: 'What does CSS stand for?',
    answers: [...],
    correct: 3
},
{
    id: 2,
     ....
}

如果没有,您将不得不使用 prevProps:

componentDidUpdate(prevProps) {
  if (this.props.question !== prevProps.question) {
    this.setState(....)
  }
}

我真的推荐key方式,因为这会强制创建一个新的组件,在实践中如果你需要不断检查变化的道具,它会变得有点难以跟踪。

记住,理想情况下应该有一个 id,因为如果问题文本相同,则会导致难以找到的严重错误。

此外,与其保存类名,不如将 selected 保存为索引并在渲染方法中选择正确的类名。

componentDidUpdate() 在更新发生后立即被调用。初始渲染不会调用此方法。 我最近遇到过这种情况。您必须在 componentDidUpdate() {} 中使用相同的代码。这是我所做的。

   componentDidUpdate(prevProps) {
      if (this.props.questions !== prevProps.questions) {
          const shuffledAnswerOptions = this.props.questions.map(question =>
          question.answer_options && 
            this.shuffleArray(question.answer_options)
          );

           this.setState({
              current_question:this.props.questions && 
               this.props.questions[0],
               question_image_url: this.props.questions && 
               this.props.questions[0] && 
             this.props.questions[0].question_image_url,
           answerOptions: shuffledAnswerOptions[0],
         numberOfQuestions: this.props.questions && 
          this.props.questions.length
          });
       }
     }

在您的情况下,您还 prevSate 参数。

这是一个示例实现:

componentDidUpdate(prevProps, prevState) {
      if(this.state.assignment !== prevState.assignment){
        document.getElementById(prevState.assignment.id) && document.getElementById(prevState.assignment.id).classList.remove("headactiveperf");
      }
      if(this.state.assessment !== prevState.assessment){
        document.getElementById(prevState.assessment.id) && document.getElementById(prevState.assessment.id).classList.remove("headactiveperf");
      }
      if(this.state.study_group_id !== prevState.study_group_id){
        document.getElementById(prevState.study_group_id) && document.getElementById(prevState.study_group_id).classList.remove("klassactiveperf");
      }
  }