'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. It seems it's not getting updated since the console log keep printing the initial values .
here's a testable 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;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
