所以我有一个setInterval和clearInterval功能来分别启动和停止计数器。这里的问题是每次我单击按钮时,状态都将设置为true,并且将触发计时器功能,从而启动计时器。现在再次单击计时器,计时器不会停止,因为refreshIntervalId变量的值现在为undefined。请帮助我!
这是我的代码:
if (timer == true) {
console.log("timer is playing");
refreshIntervalID = setInterval(timerFunction, 1000);
console.log(refreshIntervalID);
}
if (timer == false) {
console.log(refreshIntervalID);
clearInterval(refreshIntervalID);
}
这是完整的代码:
import React from "react";
import "./App.css";
import { useSelector, useDispatch } from "react-redux";
import { playToggle, reset } from "./actions/indexAction";
function Timer() {
const timer = useSelector((state) => state.timer);
const sessionLength = useSelector((state) => state.sessionLength);
let minutes = sessionLength;
let seconds = 60;
var refreshIntervalID;
const dispatch = useDispatch();
let resetClick = () => {
return dispatch(reset());
};
let timerFunction = () => {
if (timer == true) {
seconds--;
console.log(seconds);
}
};
if (timer == "reset") {
minutes = sessionLength;
seconds = 60;
console.log("Is Reset");
}
if (timer == true) {
console.log("timer is playing");
refreshIntervalID = setInterval(timerFunction, 1000);
console.log(refreshIntervalID);
}
if (timer == false) {
console.log(refreshIntervalID);
clearInterval(refreshIntervalID);
}
return (
<div>
<h1>Minutes: {minutes}</h1>
<h1>Minutes: {seconds}</h1>
<div>
<button onClick={() => dispatch(playToggle())}>PLAY/PAUSE</button>
</div>
<div>
<button onClick={resetClick}>RESET</button>
</div>
</div>
);
}
export default Timer;
答案 0 :(得分:1)
这并不完全相关,因为与之相关的评论并不完全准确:
您绝对不希望在redux reducer内产生副作用。使副作用发生在组件中。原因是减速器应该是纯净的,以使整个磁通架构正常工作。在减速器中唯一应该有副作用的情况是,如果您使用的是redux-loop之类的中间件。否则,您可以快速获得一些非常难以维护的代码。
如果这在功能组件中,请按照以下步骤操作:
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;