按钮点击后反应钩子 useInterval 重置

时间:2021-02-04 09:55:07

标签: reactjs react-hooks

我有钩子 useInterval 可以每 10 秒自动下载一次数据,但是我也有按钮可以随时手动下载数据。当我单击按钮时,我正在努力重新启动间隔计时器。所以基本上如果间隔计数到 5,但我同时点击按钮,间隔应该重新开始并在下载数据之前再次开始计数到 ​​10

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

    useEffect(() => {
        savedCallback.current = callback;
    }, [callback]);

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

        if (delay !== null) {
            const id = setInterval(tick, delay);
            return () => clearInterval(id);
        }
    }, [delay]);
};

export default useInterval;

应用部分:

useInterval(() => {
        getMessage();
      }, 10000)

const getMessage = async () => {
    setProcessing(true)
    try {
      const res = await fetch('url')
      const response = await res.json();
      setRecievedData(response)
    }
    catch (e) {
      console.log(e)
    }
    finally {
      setProcessing(false)
    }
  }

const getMessageManually = () => {
    getMessage()
    RESTART INTERVAL
  }

2 个答案:

答案 0 :(得分:1)

您应该添加一个重置函数作为从钩子返回一个值。

我还修复了一些问题并添加了卸载处理程序:

// Usage
const resetInterval = useInterval(() => ..., DELAY);
resetInterval(); 
// Implementation
const useInterval = (callback, delay) => {
  const savedCallbackRef = useRef(callback);

  const intervalIdRef = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // handle tick
  useEffect(() => {
    const tick = () => {
      savedCallback.current();
    };

    if (delay !== null) {
      intervalIdRef.current = setInterval(tick, delay);
    }

    const id = intervalIdRef.current;
    return () => {
      clearInterval(id);
    };
  }, [delay]);

  // handle unmount
  useEffect(() => {
    const id = intervalIdRef.current;
    return () => {
      clearInterval(id);
    };
  }, []);

  const resetInterval = useCallback(() => {
    clearInterval(intervalIdRef.current);
    intervalRef.current = setInterval(savedCallback.current, delay)
  }, [delay]);

  return resetInterval;
};

答案 1 :(得分:1)

您可以在钩子中添加重置函数并返回该函数。重置功能应清除现有间隔并开始新的间隔。

这是可以重置和停止的钩子的代码。

const useInterval = (callback, delay) => {
  const savedCallback = useRef(callback);
  const intervalRef = useRef(null);

  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  useEffect(() => {
    if (delay !== null) {
      const id = setInterval(savedCallback.current, delay);
      intervalRef.current = id;
      return () => clearInterval(id);
    }
  }, [delay]);

  useEffect(()=>{
    // clear interval on when component gets removed to avoid memory leaks
    return () => clearInterval(intervalRef.current);
  },[])

  const reset = useCallback(() => {
      if(intervalRef.current!==null){
        clearInterval(intervalRef.current);
        intervalRef.current = setInterval(savedCallback.current,delay)
      }
   });

   const stop = useCallback(() => {
      if(intervalRef.current!==null){
        clearInterval(intervalRef.current);
      }     
   })

  return {
    reset,
    stop
  };
};
    
// usage
const {reset,stop} = useInterval(()=>{},10000);
reset();
stop();