在倒数计时器中无法动态更新道具-使用react钩子创建

时间:2020-09-29 22:25:12

标签: reactjs react-hooks react-state

我是React的新手,正在构建一个需要从父组件动态设置倒数计时器的项目。我在网上找到了一个使用钩子的React倒数计时器,但是我对钩子还不太熟悉。

在我的代码底部,您可以看到一个父类,在该类中,我将“ cycleTimeSelected”传递给Countdown组件/挂钩。到目前为止,它一直可以正常工作。

但是我无法成功正确地动态更新计时器。 React.useState()中的timeRemaining是我需要更新的变量。如果我直接使用props.cycleTimeSelected,它将不起作用。我想我理解为什么会这样,所以我尝试使用componentWillRecieveProps设置状态,但这不起作用。

我想我对React.useState以及它与setState的关系感到困惑。有人可以在这里发现我的问题吗?

import React, { Component } from 'react'
import { PausePresentation, SkipNext, Stop, PlayCircleOutline} from '@material-ui/icons';

import './Timer.css'



function Countdown(props) {

    const [timer, setTimer] = React.useState({
      name: 'timer',
      isPaused: true,
      time: 100,
      timeRemaining: props.cycleTimeSelected,
      timerHandler: null
    })

    //const componentWillReceiveProps = nextProps => {
      //this.setState({ timeRemaining: nextProps.cycleTimeSelected });  
    //}



    const handleTimeChange = e => {
    
      setTimer({
        ...timer,
        time: props.cycleTimeSelected,
        timeRemaining: Number(e.target.value),
      })
    }

    React.useEffect(() => {
      if (timer.timeRemaining === 0) {
        clearInterval(timer.timerHandler)
      }
    }, [timer.timeRemaining, timer.timerHandler])
   
    const updateTimeRemaining = e => {
      setTimer(prev => {
        return { ...prev, timeRemaining: prev.timeRemaining - 1 }
      })
    }
    const handleStart = e => {
      const handle = setInterval(updateTimeRemaining, 1000);
      setTimer({ ...timer, isPaused: false, timerHandler: handle })
    }
    const handlePause = e => {
      clearInterval(timer.timerHandler)
      setTimer({ ...timer, isPaused: true })
    }
    return <React.Fragment>
      {/* { <input value={props.cycleTimeSelected} type="" onChange={handleTimeChange} /> } */}
        {timer.name && timer.time && <div className={timer.timeRemaining === 0 ? 'time-out':''}>
        {timer.isPaused &&  <div className="floatLeft"><i className="material-icons pause"><PlayCircleOutline onClick={handleStart}></PlayCircleOutline></i></div>}
        {!timer.isPaused &&  <div className="floatLeft"><i className="material-icons pause"><PausePresentation onClick={handlePause}></PausePresentation></i></div>}
     
        {`Remaining: ${timer.timeRemaining}`}
      </div>}
    </React.Fragment>
  }




class Timer extends React.Component {

render(){

        return(
            <>
                <div className="floatLeft"><i className="material-icons bottom-toolbar stop"><Stop onClick={this.clickStop}></Stop></i></div>
                <div className="floatLeft"><i className="material-icons bottom-toolbar skip_next"><SkipNext onClick={this.clickSkip}></SkipNext></i></div>
                <div className="floatLeft"><div id="timer"><Countdown cycleTimeSelected={this.props.cycleTimeSelected}></Countdown></div></div>
            </>
        );
    }

}

1 个答案:

答案 0 :(得分:0)

如果您希望timer.timeRemaining中的Countdown通过道具进行更新,则应实现依赖于props.cycleTimeSelected的效果。 useEffect几乎是功能组件,等效于基于类的组件的componentDidMountcomponentDidUpdatecomponentWillUnmount生命周期功能。我们对“更新”生命周期感兴趣。

useEffect(() => {
  setTimer((timer) => ({
    ...timer, // copy existing state
    timeRemaining: props.cycleTimeSelected // update property
  }));
}, [props.cycleTimeSelected]);

Edit having-trouble-making-a-prop-update-dynamically-in-countdown-timer-create-with