简体   繁体   English

clearInterval 在 React 功能组件中不起作用

[英]clearInterval not working in React functional component

I am using setInterval and clearInterval in a React functional component.我在 React 功能组件中使用setIntervalclearInterval I am incrementing the count inside the setInterval and want to clearInterval once it has reached certain value.but it is not clearing out, not sure what I am doing wrong.我正在增加setInterval内的计数,并希望在达到某个值后清除clearInterval 。但它没有清除,不确定我做错了什么。

 const { useState, useEffect } = React; /*export default*/ function App() { const [chartsCount, setChartsCount] = useState(1); useEffect(() => { const chartsCountId = setInterval(() => { setChartsCount((count) => { console.log('set chart count function is running ', { chartsCount }); if (chartsCount >= 3/*16*/) { console.log('We have reached the limit'); clearInterval(chartsCountId); } return count + 1; }); }, 1000); return () => { clearInterval(chartsCountId); }; }, [chartsCount]); return ( <div> <h1>Hello StackBlitz!</h1> <p>Start editing to see some magic happen :)</p> </div> ); } const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<App />);
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

You should handle the logic outside the setState, since you are including the count in the deps of the effect you don't need to read the fresh state in a callback:您应该处理 setState 之外的逻辑,因为您在效果的 deps 中包含count ,您不需要在回调中读取新状态:

 const { useState, useEffect } = React; /*export default*/ function App() { const [chartsCount, setChartsCount] = useState(1); useEffect(() => { const chartsCountId = setInterval(() => { if (chartsCount >= 3 /*16*/ ) { // *** console.log('We have reached the limit'); clearInterval(chartsCountId); } else { setChartsCount(c => c + 1); console.log("Current count: ", chartsCount ) } }, 1000); return () => { clearInterval(chartsCountId); }; }, [chartsCount]); // *** return ( <div> <h1>Hello StackBlitz!</h1> <p>Start editing to see some magic happen :)</p> </div> ); } const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<App />);
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

Or if you want just a simple and quick fix to your code:或者,如果您只想简单快速地修复您的代码:

 setChartsCount((count) => {
        console.log('set chart count function is running ', { chartsCount });
        if (chartsCount >= 3/*16*/) {
          console.log('We have reached the limit');
          clearInterval(chartsCountId);
          return count
        }
         return count + 1;
      });

Basically you are setting the same count if you reach the limit, and that will prevent the effect from running again.基本上,如果达到限制,您将设置相同的计数,这将阻止效果再次运行。

The problem is that you've made chartsCount a dependency on the useEffect , so every time it changes one interval is canceled and another is started.问题是您已经使chartsCount成为 useEffect 的依赖useEffect ,因此每次更改时都会取消一个间隔并启动另一个间隔。 That includes when the count has gone above the limit, since you're still adding to the count in that case.包括当计数超过限制时,因为在这种情况下您仍在增加计数。

Instead:反而:

  1. Don't make chartsCount a dependency of the effect, and不要让chartsCount成为效果的依赖项,并且
  2. Use count (the parameter if your setChartsCount callback) rather than chartsCount in your effect code在效果代码中使用count (如果您的setChartsCount回调的参数)而不是chartsCount

Updated snippet, see the four comments with *** :更新的代码片段,请参阅带有***的四个评论:

 const { useState, useEffect } = React; /*export default*/ function App() { const [chartsCount, setChartsCount] = useState(1); useEffect(() => { const chartsCountId = setInterval(() => { setChartsCount((count) => { console.log('set chart count function is running ', { chartsCount: count }); // *** if (count >= 3/*16*/) { // *** console.log('We have reached the limit'); clearInterval(chartsCountId); return count; // *** >>IF<< you don't want count incremented the last time } return count + 1; }); }, 1000); return () => { clearInterval(chartsCountId); }; }, []); // *** return ( <div> <h1>Hello StackBlitz!</h1> <p>Start editing to see some magic happen :)</p> </div> ); } const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<App />);
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM