react setInterval does not end



我在else语句中设置了setIsRunning(false)后,它应该出去console.log('final call')。但它一直调用console.log('running')。有人知道我在这里做错了什么,以及如何解决这个问题吗?

const [val, setval] = useState(0)
const [isRunning, setIsRunning] = useState(true)
useEffect(() => {
let intervalId
if (isRunning) {
intervalId = setInterval(() => {
if (val <= 100) {
setval((t) => t + 5)
} else {
console.log('call')
setIsRunning(false)
}
console.log('running') // This is being called continuously
}, 50)
} else {
console.log('final call')
}
return () => clearInterval(intervalId)
}, [isRunning])

一旦val达到100,我希望setTimeout停止,但同时我不想在我的依赖中使用val。我想要清除间隔,以便它不再运行

试试我的代码

const [val, setval] = useState(0);
const [isRunning, setIsRunning] = useState(true);
useEffect(() => {
let intervalId;
if (isRunning) {
intervalId = setInterval(() => {
setval((t) => {
if (t <= 100) {
return (t += 5);
} else {
setIsRunning(false);
clearInterval(intervalId);
return t;
}
});
console.log('running'); // This is being called continuously
}, 50);
} else {
console.log('final call');
}
return () => clearInterval(intervalId);
}, [isRunning]);

你的代码有两个问题。

  1. 不要将state作为useEffect的依赖项。

  2. 您的if条件必须在setInterval内,而不是不在setInterval内。

作为一个建议,使用Ref代替State。

所以这是预期的:

const valRef = useRef(0)
const isRunningRef = useRef(true);
useEffect(() => {
let intervalId;
intervalId = setInterval(() => {
if (isRunningRef.current) {
if (valRef.current <= 100) {
valRef.current += 5;
} else {
console.log('call');
isRunningRef.current = false;
}
console.log('running');
} else {
console.log('final call');
clearInterval(intervalId);
}
}, 50)
return () => clearInterval(intervalId)
}, [])

快速修复

const [val, setval] = useState(0)
// const [isRunning, setIsRunning] = useState(true)
// use useRef if you dont want to react to changes in useEffect
const isRunningRef = useRef(true)
useEffect(() => {
let intervalId
if (isRunning.current) {
intervalId = setInterval(() => {
if (val <= 100) {
setval((t) => t + 5)
} else {
console.log('call')
isRunning.current = false;
// stop the interval here if needed
clearInterval(intervalId)
}
console.log('running') // This is being called continuously
}, 50)
} 
return () => {
if (intervalId !== undefined) {
// clear if only timer was set
clearInterval(intervalId)
}
}
}, []) // userRef varaibles not needed in depedency array

React beta文档解释了这个问题,但解决方案是使用RFC中的useEvent,所以useRef可以使用到那时

希望它能解决你的问题

相关内容

最新更新