[英]useEffect won't update state
I'm creating a simple tomato app and got stuck on the timer update logic.我正在创建一个简单的番茄应用程序并卡在计时器更新逻辑上。
I'm using a useEffect
to update a timer, but for some reason after the one second, the timer stop decreasing.我正在使用useEffect
来更新计时器,但由于某种原因,一秒钟后,计时器停止减少。 It seems it's not getting updated since the console log keep printing the initial values.它似乎没有得到更新,因为控制台日志不断打印初始值。
here's a testable stackbliz这是一个可测试的stackbliz
here's the full component:这是完整的组件:
import './Tomato.css';
import { useState, useEffect } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlay, faPause, faArrowsRotate, faArrowDown, faArrowUp } from '@fortawesome/free-solid-svg-icons'
function Tomato() {
const [settings, setSettings] = useState({session: 25, break: 5});
const [timer, setTimer] = useState({minutes: '25', seconds: '00', active: false, isBreak: false});
useEffect(() => {
let timerInterval;
if(timer.active) {
timerInterval = setInterval(() => {
let seconds = parseInt(timer.seconds);
let minutes = parseInt(timer.minutes);
console.log(seconds, ':',minutes)
if(seconds === 0 && minutes === 0) {
// setTimer( {
// minutes: settings.isBreak ? settings.session : settings.break,
// seconds: '00',
// active: true,
// isBreak: !settings.isBreak
// })
// // TODO BIP
} else if(seconds === 0) {
const newTimer = {
...timer,
minutes: timer.minutes-1,
seconds: '59',
}
setTimer( newTimer)
} else {
console.log('in')
seconds = seconds - 1;
// this is not working as expected
setTimer( {
...timer,
seconds: seconds < 10 ? '0'+seconds : seconds+''
})
}
}, 1000);
} else {
clearInterval(timerInterval);
}
return function cleanup() {
clearInterval(timerInterval);
};
}, [timer.active]);
const toggleTimer = (value) => {
setTimer({ ...timer, active: value})
}
const refreshTimer = () => {
setTimer({
minutes: settings.session,
seconds: '00',
active: false,
isBreak: false
})
}
const editSettings = (type, val) => {
if(timer.active) return
const newSettings = { ...settings }
newSettings[type] +=val;
if(newSettings[type] > 60) {
newSettings[type] = 60
}
if(newSettings[type] < 1) {
newSettings[type] = 1
}
setSettings(newSettings)
}
return (
<div className="Tomato">
<h2 className="title">Session</h2>
<div className="session-container">
<div className='session-value'>{timer.minutes}:{timer.seconds}</div>
<div className='controls-container'>
<span className='icon-container'>
<FontAwesomeIcon onClick={()=>{ toggleTimer(true)}} icon={faPlay} />
</span>
<span className='icon-container'>
<FontAwesomeIcon onClick={()=>{ toggleTimer(false)}} icon={faPause} />
</span>
<span className='icon-container'>
<FontAwesomeIcon onClick={()=>{ refreshTimer()}} icon={faArrowsRotate} />
</span>
</div>
</div>
<h2 className="title">Session Length</h2>
<div className="setting-container">
<span className='icon-container' onClick={()=> editSettings('session', -1)}>
<FontAwesomeIcon icon={faArrowDown} />
</span>
<div className="setting-value">{settings.session}</div>
<span className='icon-container' onClick={()=> editSettings('session', 1)}>
<FontAwesomeIcon icon={faArrowUp} />
</span>
</div>
<h2 className="title">Break Length</h2>
<div className="setting-container">
<span className='icon-container' onClick={()=> editSettings('break', -1)}>
<FontAwesomeIcon icon={faArrowDown} />
</span>
<div className="setting-value">{settings.break}</div>
<span className='icon-container' onClick={()=> editSettings('break', +1)}>
<FontAwesomeIcon icon={faArrowUp} />
</span>
</div>
</div>
);
}
export default Tomato;
That's the typical stale state issue, timer
inside the interval is stale since you are not placing it into the effect deps.这是典型的陈旧 state 问题,间隔内的timer
是陈旧的,因为您没有将它放入效果部门。 Just change timer.active
to timer
in the deps array.只需将 deps 数组中的timer.active
更改为timer
即可。
...
return function cleanup() {
clearInterval(timerInterval);
};
}, [timer]);
If you want to know more about this specific issue: https://overreacted.io/making-setinterval-declarative-with-react-hooks/如果您想了解有关此特定问题的更多信息: https://overreacted.io/making-setinterval-declarative-with-react-hooks/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.