我是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>
</>
);
}
}
答案 0 :(得分:0)
如果您希望timer.timeRemaining
中的Countdown
通过道具进行更新,则应实现依赖于props.cycleTimeSelected
的效果。 useEffect
几乎是功能组件,等效于基于类的组件的componentDidMount
,componentDidUpdate
和componentWillUnmount
生命周期功能。我们对“更新”生命周期感兴趣。
useEffect(() => {
setTimer((timer) => ({
...timer, // copy existing state
timeRemaining: props.cycleTimeSelected // update property
}));
}, [props.cycleTimeSelected]);