Это не совсем актуально, так как комментарий, с которым это было связано, оказался не совсем точным:
Вы абсолютно не хотите иметь побочные эффекты в редукторном редукторе. Вместо этого сделайте побочные эффекты в компоненте. Причина в том, что редукторы должны быть чистыми, чтобы вся архитектура потока работала правильно. Единственный раз, когда в редукторе должны быть побочные эффекты, это если вы используете промежуточное программное обеспечение, такое как redux-l oop. В противном случае вы можете быстро получить некоторый очень не поддерживаемый код.
Если это функциональный компонент, вот как я это делаю:
function(){
useEffect(()=>{
if (timer) {
console.log("timer is playing");
const refreshIntervalID = setInterval(timerFunction, 1000);
console.log(refreshIntervalID);
return ()=>{
clearInterval(refreshIntervalID)
}
}
},[timer])
}
Вы должны очистить интервал в хуке useEffect
Редактировать: добавить, надеюсь, рабочий код
import React, { useEffect, useState } from 'react';
import './App.css';
import { useSelector, useDispatch } from 'react-redux';
import { playToggle } from './actions/indexAction';
function Timer() {
const timer = useSelector((state) => state.timer);
const sessionLength = useSelector((state) => state.sessionLength * 60); // session in seconds
const [seconds, setSeconds] = useState(sessionLength);
const [resetTimer, setResetTimer] = useState(0);
const dispatch = useDispatch();
let resetClick = () => {
// Get a new value every time
setSeconds(sessionLength);
setResetTimer((value) => value + 1);
};
useEffect(()=>{
// Set the timer to use the latest value when the session length changes.
setSeconds(sessionLength)
},[sessionLength])
useEffect(() => {
// Perform a side effect
if (timer) {
// Only run the timer when timer is truthy
let timerFunction = () => {
setSeconds((seconds) => seconds - 1);
};
console.log('timer is playing');
const refreshIntervalID = setInterval(timerFunction, 1000);
return () => {
// Clean up timer before effect runs again (or on unmount)
clearInterval(refreshIntervalID);
};
}
// Restart timer whenever timer, sessionLength, or resetTimer changes
}, [timer, resetTimer]);
useEffect(() => {
// If the timer has elapsed, stop the timer and reset.
if (seconds <= 0) {
dispatch(playToggle());
setSeconds(sessionLength);
}
}, [seconds, dispatch, sessionLength]);
return (
<div>
<h1>Minutes: {Math.floor(seconds / 60)}</h1>
<h1>Minutes: {seconds % 60}</h1>
<div>
<button onClick={() => dispatch(playToggle())}>PLAY/PAUSE</button>
</div>
<div>
<button onClick={resetClick}>RESET</button>
</div>
</div>
);
}
export default Timer;