react-countdown-now-在父组件上调用setState时防止重新渲染

时间:2019-08-28 18:05:20

标签: reactjs timer state countdown

我是一个很新的反应者,正在构建一个测验反应应用程序。每个测验都有一个时间限制,该时间限制通过道具使用https://github.com/ndresx/react-countdown

通过道具传递给倒数计时器组件

我将以秒为单位存储时间,并以父组件的状态存储从4个选项中选择的答案。

问题是,每次我调用setState并从孩子那里获得所选答案时,计时器都会重新启动为初始状态,因为整个组件都会重新显示(例如,测验从03:00分钟开始,计时器同时倒计时至02:00,然后用户选择答案,计时器重置为03:00)

我尝试在父级中实现shouldComponentUpdate来检查当前时间是否等于初始时间,但是它阻止了对整个页面的任何状态更新(存储在状态中的答案标记为所选答案)。我也尝试在父级上使用PureComponent,但这并没有改变问题。

这是它的外观:enter image description here

某些代码:

具有selectAnswer功能的父组件,该组件设置状态并对此问题负责(道具的来源来自路由重定向)

class ExamWindow extends Component {

 constructor(props) {
     super(props);

     this.state = {
         currentExam: this.props.history.location.state.currentExam,          
     questions:this.props.history.location.state.currentExam.questions,
        timeleft: this.props.history.location.state.currentExam.time,
        selectedAnswers: [],
        currentQuestionIndex: 0,
    }

    selectAnswer = (answerIndex) => {
        let newSelectedAnswers = [...this.state.selectedAnswers];
       newSelectedAnswers[this.state.currentQuestionIndex] = answerIndex;

    this.setState((state, props) => ({
        selectedAnswers: newSelectedAnswers,
        timeleft: state.timeleft
    }));

}
}

存储计时器的组件(位于父级的render()中)

<ExamInfoBox currentQuestionNumber={this.state.currentQuestionIndex+1} 
             totalQuestionsAmount={this.state.questions.length}
             time={this.state.timeleft}
>
</ExamInfoBox>

包含考试答案的组件

Answers = (props) => {
    return (
        <div className="exam-answers">
            { 
                times(4, (i) => {
                    return (
                        <div className={classNames("exam-answer", this.isSelected(i+1) ? 'active' : '')}
                        key={i} 
                        onClick={() => this.selectAnswer(i+1)}>
                            <span className='answer'>
                                {i}
                            </span>
                        </div>
                    )
                })
            }
        </div>
    )
}

包含考试答案的组件(在家长的render()中)

<this.Answers question={props.question}/>

谢谢您的帮助!

1 个答案:

答案 0 :(得分:0)

import React, { useState, useEffect} from 'react';

const Questions = ({ onStagePass,stageNum}) => {
  return (
    <div>
      Stage Number {stageNum}
      <button onClick={onStagePass}>
        Next Stage
      </button>
    </div>
  )
};

export const Exam = () => {
  const [timeLeft, setTimeLeft] = useState(400);
  const [stageNum, setStageNum] = useState(1);

  useEffect( () => {
    const timerInterval = setInterval(() => setTimeLeft(timeLeft => timeLeft -1),1000);
    return () => clearInterval(timerInterval);  
  },[]);

  return (
  <div>
      Time Left: {timeLeft}
      <Questions onStagePass={() => setStageNum(stageNum+1)} stageNum={stageNum} />
    </div>
  )
};