如何使用componentDidMount重置状态?

时间:2020-03-06 14:01:49

标签: reactjs react-state

我是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;

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

下面是整个项目的链接:

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

4 个答案:

答案 0 :(得分:1)

对此有一个简单的解决方法(建议作为React最佳实践),如果您更改答案的key,则可以进行演示: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作为索引并在render方法上选择正确的类名,而不是保存类名。

答案 1 :(得分:0)

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


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;

答案 2 :(得分:0)

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");
      }
  }

答案 3 :(得分:-1)

问题在于,如果您在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