SetInterval on mount for a set duration

SetInterval on mount for a set duration

我在这里进行了一些问答,但无法理解我做错了什么。以下组件在控制台中打印 0s,但未按预期更新 DOM。

const NotifPopup = ({ notif, index, closeHandler }) => {
  const [timer, setTimer] = useState(0);

  useEffect(() => {
    const timerRef = setInterval(() => {
      if (timer === 3) {
        clearInterval(timerRef);
        closeHandler(index);
      } else {
        console.log("timer", timer);
        setTimer(timer + 1);
      }
    }, 1000);
  }, []); // only run on mount

  return (<div className="notifPopup">
    <span className=""></span>
    <p>{notif.message}</p>
    <span className="absolute bottom-2 right-8 text-xs text-oldLace">{`closing in ${timer}s`}</span>
  </div>);
};

为什么 setInterval 在控制台中打印 0 流而不更新 DOM?

由于关闭,您正在登录、比较和设置过时值。

在相关问题中查看更多use cases

useEffect(() => {
  // timerRef from useRef
  timerRef.current = setInterval(() => {
    setTimer((prevTimer) => prevTimer + 1);
  }, 1000);
}, []);

useEffect(() => {
  console.log("timer", timer);
  if (timer === 3) {
     clearInterval(timerRef.current);
  } 
}, [timer]);

查看 the code for useInterval in react-use。检查此包中的不同挂钩可以大大提高您对挂钩的理解。

import { useEffect, useRef } from 'react';

const useInterval = (callback: Function, delay?: number | null) => {
  const savedCallback = useRef<Function>(() => {});

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

  useEffect(() => {
    if (delay !== null) {
      const interval = setInterval(() => savedCallback.current(), delay || 0);
      return () => clearInterval(interval);
    }

    return undefined;
  }, [delay]);
};

export default useInterval;

docs中描述的用法:

import * as React from 'react';
import {useInterval} from 'react-use';

const Demo = () => {
  const [count, setCount] = React.useState(0);
  const [delay, setDelay] = React.useState(1000);
  const [isRunning, toggleIsRunning] = useBoolean(true);

  useInterval(
    () => {
      setCount(count + 1);
    },
    isRunning ? delay : null
  );

  return (
    <div>
      <div>
        delay: <input value={delay} onChange={event => setDelay(Number(event.target.value))} />
      </div>
      <h1>count: {count}</h1>
      <div>
        <button onClick={toggleIsRunning}>{isRunning ? 'stop' : 'start'}</button>
      </div>
    </div>
  );
};

要在挂载上启动间隔,只需更改 isRunning on mount 的值:

useMount(()=>{
     toggleIsRunning(true);
});