【问题标题】:How to get setInterval to run callback function once before applying delay如何在应用延迟之前让 setInterval 运行一次回调函数
【发布时间】:2019-04-30 11:30:43
【问题描述】:

我在 useEffect 挂钩中运行 setInterval 来循环一个函数,但是,我希望能够在应用延迟(间隔)之前先运行该函数一次。有没有办法在应用延迟之前在 useEffect 挂钩中运行该函数一次?

我曾尝试在 setInterval 函数之前在钩子内运行一次该函数,但它没有给我希望的结果。在 useEffect 挂钩之外运行函数也是如此。

  const myText = props.text;
  const textTimeout = 100;
  const funTextInterval = textTimeout * myText.length
  const [quickText, setQuickText] = useState([]);

  const setDelay = (i) => {
    setTimeout(() => {
       myFunction();
     , textTimeout * i);
  };

  useEffect(() => {
    setInterval(() => {
      for (let i = 0; i < myText.length + 1; i++) {
        setDelay(i);
      }
    }, funTextInterval);    
  }, []);

我希望 forloop 在 setInterval 延迟开始之前运行一次,但延迟发生在 forloop 之前

【问题讨论】:

  • 您确定延迟不是来自setTimeout(),而是来自间隔吗?
  • ^^ 那。 setInterval()setTimeout() 的组合导致了您的问题。

标签: javascript reactjs react-hooks


【解决方案1】:

取出方法中的for循环逻辑,并在setInterval之前和setInterval内部调用它

const myText = props.text;
  const textTimeout = 100;
  const funTextInterval = textTimeout * myText.length
  const [quickText, setQuickText] = useState([]);

  const setDelay = (i) => {
    setTimeout(() => {
       myFunction();
     , textTimeout * i);
  };

  useEffect(() => {
    const loop = () => {
      for (let i = 0; i < myText.length + 1; i++) {
        setDelay(i);
      }
    }
    loop();
    setInterval(() => {
      loop();
    }, funTextInterval);    
  }, []);

【讨论】:

    【解决方案2】:

    你可以像这样分离你的逻辑:

      const myText = props.text;
      const textTimeout = 100;
      const funTextInterval = textTimeout * myText.length
      const [quickText, setQuickText] = useState([]);
    
      function applyTextEffect() {
          for (let i = 0; i < myText.length + 1; i++) {
            setTimeout(myFunction, textTimeout * i);
          }
      }
    
      useEffect(() => {
        applyTextEffect()  // call it here immediately to get the effect you want.
        setInterval(applyTextEffect, funTextInterval);    
      }, []);
    

    但请注意,此组件将通过在每次更新时调用您的文本效果函数来创建不需要的效果。 UseEffect 在每次更新中都有效。最好有一个 isMounted 状态变量并围绕它实现逻辑以仅应用一次效果。

    编辑:存储从 setInterval 函数返回的间隔 id 并将其清除以返回 useEffect 也是明智的。否则当你的组件被销毁时,你会得到异常

    【讨论】:

      【解决方案3】:

      仅使用 for 循环编写一个单独的函数。
      在调用 useEffect() 之前调用该函数。
      从 useEffect() -> setInterval() 内部,调用新方法。

      下面给出未经测试的代码以作说明。

      const myText = props.text;
      const textTimeout = 100;
      const funTextInterval = textTimeout * myText.length
      const [quickText, setQuickText] = useState([]);
      
      const setDelay = (i) => {
        setTimeout(() => {
           myFunction();
         , textTimeout * i);
      };
      
      runloop(){
        for (let i = 0; i < myText.length + 1; i++) {
          setDelay(i);
        }
      }
      
      useEffect(() => {
        setInterval(() => {
          runloop()
        }, funTextInterval);    
      }, []);
      
      runloop();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-22
        • 1970-01-01
        相关资源
        最近更新 更多