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

clearInterval not working in React functional component

我在 React 功能组件中使用 setIntervalclearInterval。我正在增加 setInterval 内的计数,并希望 clearInterval 一旦它达到某个值 value.but 它不会清除,不确定我做错了什么。

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>

问题是您已经使 chartsCount 成为 useEffect 的依赖项,因此每次它发生变化时,都会取消一个间隔并启动另一个间隔。当计数超过限制时,包括,因为在这种情况下您仍在添加计数。

改为:

  1. 不要让chartsCount成为效果的依赖项,并且
  2. 在效果代码中使用 countsetChartsCount 回调的参数)而不是 chartsCount

已更新代码段,查看带有 *** 的四个评论:

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>

您应该在 setState 之外处理逻辑,因为您将 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>

或者如果您只想简单快速地修复您的代码:

 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;
      });

基本上,如果达到限制,您将设置相同的计数,这将防止效果再次 运行。