【问题标题】:SetInterval on mount for a set durationSetInterval on mount 一段设定的时间
【发布时间】:2021-09-26 06:05:35
【问题描述】:

我在这里完成了一些问答,但无法理解我做错了什么。以下组件在控制台中打印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 在控制台打印0s 流而不更新DOM?

【问题讨论】:

    标签: javascript reactjs asynchronous setinterval


    【解决方案1】:

    由于关闭,您正在登录、比较和设置一个陈旧的值。

    在相关问题中查看更多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]);
    

    【讨论】:

      【解决方案2】:

      查看the code 以了解react-use 中的useInterval。检查这个包中的不同钩子可以大大提高你对钩子的理解。

      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 的值:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-27
        • 1970-01-01
        相关资源
        最近更新 更多