Have you considered turning your timer into a custom hook? Here's a timer I use...
import { useEffect, useState } from 'react';
const useCountdown = (targetDate: number) => { const [countDown, setCountDown] = useState( targetDate - new Date().getTime() );
useEffect(() => { const interval = setInterval(() => { setCountDown(targetDate - new Date().getTime()); }, 1000);
return () => clearInterval(interval);
}, [targetDate]);
return getReturnValues(countDown); };
const getReturnValues = (countDown: number) => { // calculate time left const minutes = Math.floor((countDown % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((countDown % (1000 * 60)) / 1000);
return [minutes, seconds]; };
export { useCountdown };
With a showCounter component:
const ShowCounter: React.FC<ITimer> = (props): JSX.Element => { const [ minutes, seconds ] = useCountdown(props.currentTimer); const navigate = useNavigate();
useEffect(() => { if ( minutes + seconds <= 0 ) { navigate('/end'); }; }, [minutes, seconds])
return ( <Chip sx={{width: 260, height: 50, fontSize: 16}} icon={<AccessTimeIcon />} variant='outlined' color='primary' label={minutes + ' min : ' + seconds +' sec'} size='medium'/> ); };
Called in a view component:
const Questions: React.FC = (): JSX.Element => {
const now: number = new Date().getTime();
const [currentTimer, setTimer] = useState<number>(now + (60 * 1000));
return (
<Container sx={{display: "flex", flexDirection: "column", alignItems: "center", height: "100vh"}} maxWidth = 'xs'>
<br />
<TimerDiv>
<CountdownTimer stateVar = {currentTimer} stateFunction = {setTimer}/>
</TimerDiv>
<br />
<QuestionsDiv>
<Outlet />
</QuestionsDiv>
</Container>
);
};