首页 > 解决方案 > 当分数为 0 时反应 setState

问题描述

我正在做一个测验,现在我想根据用户的分数向用户显示不同的消息。此代码正在运行,但是当分数为 0 时,我没有设置新状态。

似乎与 prevProps.score 仅在您正确回答某些内容时才会触发有关。是否有其他条件我可以使用?

以下是当前状态下的所有代码:

class App extends React.Component {

    constructor(props) {
        super(props);

        // Make it somewhat harder for cheaters to inspect the correct answer.
        document.getElementById('quiz').setAttribute('data-props', '');

        const data = JSON.parse(this.props.quiz);

        this.state = {
            data: data,
            nr: 0,
            total: data.length,
            showButton: false,
            questionAnswered: false,
            score: 0,
            popUpClass: 'popup-visible',
            quizVisible: false,
            id: data[0].id,
            question: data[0].question,
            answers: [
                data[0].answers[0], 
                data[0].answers[1], 
                data[0].answers[2], 
                data[0].answers[3]
            ],
            correct: data[0].correct
        }



        this.nextQuestion = this.nextQuestion.bind(this);
        this.handleShowButton = this.handleShowButton.bind(this);
        this.handleStartQuiz = this.handleStartQuiz.bind(this);
        this.handleIncreaseScore = this.handleIncreaseScore.bind(this);        
    }

    pushData(nr) {
        const data = this.state.data;
        this.setState({
            question: data[nr].question,
            answers: [data[nr].answers[0], data[nr].answers[1], data[nr].answers[2], data[nr].answers[3] ],
            correct: data[nr].correct,
            nr: this.state.nr + 1
        });
    }

    nextQuestion() {
        let { nr, total} = this.state;

        if(nr === total){
            this.setState({
                popUpClass: 'popup-visible',
                quizVisible: false
            });
        } else {
            this.pushData(nr);          
            this.setState({
                showButton: false,
                questionAnswered: false,
                quizVisible: true
            });
        }  
    }

    handleShowButton() {
        this.setState({
            showButton: true,
            questionAnswered: true
        });
    }

    handleStartQuiz() {
        this.setState({
            popUpClass: 'popup-hidden',
            quizVisible: true,
            nr: 1
        });
    }

    handleIncreaseScore() {
        this.setState({
            score: this.state.score + 1
        });
    }

    render() {
        let { nr, total, id, question, answers, correct, showButton, questionAnswered, popUpClass, quizVisible, score} = this.state;

        return (
            <div className="app-container">
                <Popup className={popUpClass} score={score} total={total} startQuiz={this.handleStartQuiz} key={nr} />           
                    {quizVisible ? 
                    (         
                        <div key={question} className="quiz"> 
                            <div className="quiz-box">
                            <span className="question-total">Fråga {nr} av {total}</span>
                            <h2 className="question">{question}</h2> 
                            <Answers 
                            key={id}
                            answers={answers} 
                            correct={correct} 
                            showButton={this.handleShowButton} 
                            isAnswered={questionAnswered} 
                            increaseScore={this.handleIncreaseScore} /> 
                            </div>
                            <div id="submit">
                               {showButton ? <button className="fancy-btn" onClick={this.nextQuestion} id={nr === total ? 'finishQuiz' : null}>{nr === total ? 'Slutför quiz' : 'Nästa fråga'}</button> : null}
                            </div>
                        </div>                     
                    ) : null}         

            </div>        
        );
    }
};

class Popup extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            title: 'Quiz',
            showStartButton: true
        };

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

    startQuizHandle() {                   
        this.props.startQuiz();
    }

    componentDidUpdate(prevProps) {

        let total = this.props.total;
        let highScore = total - 2;
        let halfScore = total / 2;

        if (this.props.score !== prevProps.score) {
            if (this.props.score >= highScore) {

                this.setState({
                    title: 'You are an expert!',
                })
            } else if (this.props.score >= halfScore && this.props.score <= highScore) {

                this.setState({
                    title: 'You are pretty good at this!'
                })
            }
            else if (this.props.score < halfScore && this.props.score > 0) {
                console.log('score less than half');
                this.setState({
                    title: 'You need some practice.'
                })
            }
            else {
                this.setState({
                    title: 'You did not do too well.',
                })
            }
        }
    }

    createMarkup(text) {
        return {__html: text};
    }   

    render() {

        let { title, intro, text, showStartButton } = this.state;
        let { className } = this.props;

        return (
            <div className={`popup-container ${ className }`}>
                <div className="popup">
                    <h1>{title}</h1>
                </div>
                {showStartButton ? <button className="fancy-btn" onClick={this.startQuizHandle}>Start Quiz</button> : null}

            </div>
        );
    }
}

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

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

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

        this.setState({
            isDisabled: true
        })

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

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

        return (
            <div id="answers">
                <ul>
                    <li onClick={this.checkAnswer} className={classNames[0]} data-id="1"><p className={isDisabled ? "disabled" : null}><span>A</span> {answers[0]}</p></li>
                    <li onClick={this.checkAnswer} className={classNames[1]} data-id="2"><p className={isDisabled ? "disabled" : null}><span>B</span> {answers[1]}</p></li>
                    <li onClick={this.checkAnswer} className={classNames[2]} data-id="3"><p className={isDisabled ? "disabled" : null}><span>C</span> {answers[2]}</p></li>
                </ul>
            </div>
        );
    }
}

export default Answers

标签: reactjs

解决方案


将您的最后一个转换else if为一个,else以便您的条件测试如下:

  • 如果分数 >= 高分 => “...专家!”
  • 否则,如果半分 <= 分数 < 高分 => "... 有点好"
  • else if 0 < score < half score => "..need practice"
  • else =>“做得不好”

这是未落入先前测试用例之一的分数的逻辑的“包罗万象”分支。

componentDidUpdate

componentDidUpdate(prevProps) {
  let total = this.props.total;
  let highScore = total - 2;
  let halfScore = total / 2;

  const { score } = this.props;

  if (score !== prevProps.score) {
    if (score >= highScore) {
      this.setState({
        title: "You are an expert!"
      });
    } else if (score >= halfScore && score <= highScore) {
      this.setState({
        title: "You are pretty good at this!"
      });
    } else if (score < halfScore && score > 0) {
      this.setState({
        title: "You need some practice."
      });
    } else {
      this.setState({
        title: "You did not do too well."
      });
    }
  }
}

编辑 stoic-tdd-8utd6

编辑

看起来您的初始测验状态是total数据数组的长度(大概是测验问题?)并score. 0根据您的逻辑,很明显score单调增加。我认为组件中缺少的部分是检查这个“初始状态”,其中. 我的猜测是您会看到从第一个正确答案开始,然后在第一个正确答案之后更新为. 内部的“检查分数”逻辑的一个小重构将允许您在第一次安装时检查 0Popupscore === 0title"Quiz" "You need some practice."componentDidUpdatePopupscore 0

checkScore = () => {
  const { score, total } = this.props;
  const highScore = total - 2;
  const halfScore = total / 2;

  if (score >= highScore) {
    this.setState({
      title: "You are an expert!"
    });
  } else if (score >= halfScore && score < highScore) {
    this.setState({
      title: "You are pretty good at this!"
    });
  } else if (score < halfScore && score > 0) {
    this.setState({
      title: "You need some practice."
    });
  } else {
    this.setState({
      title: "You did not do too well."
    });
  }
}

componentDidMount() {
  this.checkScore();
}

componentDidUpdate(prevProps) {
  const { score } = this.props;

  if (prevProps.score !== score) {
    this.checkScore();
  }
}

更新了上面链接的代码框。


推荐阅读