React:使用间隔不清除

React: Use Interval Not Clearing

一旦 joke 数组有 5 个笑话作为对象,我将尝试清除 useInterval 函数。但是,我不确定我做错了什么。完整代码:https://codesandbox.io/s/asynchronous-test-mp2fq?file=/AutoComplete.js

 const [joke, setJoke] = React.useState([]);

  function useInterval(callback, delay) {
    const savedCallback = useRef();

    let id;

    useEffect(() => {
      savedCallback.current = callback;
      if (joke.length === 5) {
        console.log("5 STORED AND CLEARED INTERVAL");
        return () => clearInterval(id);
      }
    });

    useEffect(() => {
      function tick() {
        savedCallback.current();
      }

      id = setInterval(tick, delay);
      return () => clearInterval(id);
    }, [delay]);
  }

  useInterval(() => {
    // setJoke(joke);
    axios.get("https://api.chucknorris.io/jokes/random").then((res) => {
      setJoke(joke.concat(res.data.value));
      console.log("JOKE: ", joke);
    });

    console.log("Every 5 seconds");
  }, 5000);

尝试将 callback 添加到您的依赖项数组

    useEffect(() => {
      savedCallback.current = callback;
      if (joke.length === 5) {
        console.log("5 STORED AND CLEARED INTERVAL");
        return () => clearInterval(id);
      }
    },[callback]);

使用 ref 存储间隔 ID,以在重新渲染之间保留它。当长度为 5 时,调用 clearInterval 而不是返回一个干净的函数,该函数将在组件卸载时调用。

此外,通过提供 stop 函数并在组件重新呈现时调用它,使挂钩与实际停止条件无关。

function useInterval(callback, delay, stop) {
  const savedCallback = useRef();
  const interval = useRef();

  useEffect(() => {
    savedCallback.current = callback;
    
    if (stop?.()) { // call stop to check if you need to clear the interval
      clearInterval(interval.current); // call clearInterval
    }
  });

  useEffect(() => {
    function tick() {
      savedCallback.current();
    }

    interval.current = setInterval(tick, delay); // set the current interval id to the ref

    return () => clearInterval(interval.current);
  }, [delay]);
}

const Example () => {
  const [joke, setJoke] = React.useState([]);
  
  useInterval(() => {
    // setJoke(joke);
    axios.get("https://api.chucknorris.io/jokes/random").then((res) => {
      setJoke(joke.concat(res.data.value));
      console.log("JOKE: ", joke);
    });

    console.log("Every 5 seconds");
  }, 5000, () => joke.length > 4);
  
  return (
    ...
  );
};