【问题标题】:How to write a timer interval that is dependent on a prop in react?如何编写一个依赖于反应道具的计时器间隔?
【发布时间】:2021-04-14 11:10:14
【问题描述】:

我正在为我的网站创建一个简单的弹出窗口组件,并且我想定期收集大约每秒左右的任何新消息或传入消息,以实现实时消息传递功能。我目前正在为我的项目使用 react。

我的主要问题是,我只想在名为“active”的道具设置为 True 时收集消息,但我不知道该怎么做。

这是我的网页模型,希望对您有所帮助。 It is of a mockup of the webpage and has three entries, one with an open messaging window.

我有多个条目可以打开它们的消息窗口,但我已经传递了其他道具,因此一次只能打开一个消息窗口。因此,可以在组件的祖先之一中设置一个间隔/计时器,但我想通过它自己对 API 的调用使这个弹出窗口更加自给自足。

我尝试使用 setInterval 函数,该函数在消息窗口组件内的 useEffect 函数中进行初始化:

    let my_interval = useRef() // ???? Don't think this is the solution

    const timerHandler = useCallback(() => {
        // Some call to my RestAPI here.
        console.log("Timer called")
    }, active)

    // If the "active" prop turns true, the interval should be running. Else, clear the interval if it exists.
    // Here, the trouble is the interval handle "my_interval" is changing so I can't clear the original interval.
    useEffect(() => {
        if (active) my_interval = setInterval(timerHandler, 1000);
        else if (!active) clearInterval(my_interval)
    }, [active])

但是,正如评论指出的那样,我实际上无法清除间隔,因为我找不到使间隔句柄 my_interval 足够稳定的方法(useRef 不起作用)

我还尝试使用带有递归调用的超时函数,只要 active 为真,它就会一直调用它自己,但我认为我有一个类似的问题,因为函数本身正在改变,所以 递归调用有点坏了。

    // Only do action when active is set to true. This doesn't work, when active changes to false the timer still runs.
    const timeoutHandler = useCallback(() => { 
        if (active) console.log("Timer called")
        setTimeout(timeoutHandler, 1000);
    }, [active])

    // Set a timeout on render, regardless of "active"
    useEffect(() => {
        setTimeout(timeoutHandler, 1000);
    }, [])

任何帮助或不同的策略将不胜感激,我真的希望我的信使弹出窗口能够自给自足地调用我的 RestAPI,但在这一点上似乎几乎不可能。

【问题讨论】:

    标签: reactjs timer setinterval react-props


    【解决方案1】:

    useRef 是一个对象,see docs 的 API:

    const intervalRef = useRef();
    
    // handle on active state change
    useEffect(() => {
      if (active) {
        intervalRef.current = setInterval(() => {
          console.log("Timer called");
        }, 1000);
      } else {
        clearInterval(intervalRef.current);
      }
    }, [active]);
    
    // handle unmount
    useEffect(() => {
      const intervalId = intervalRef.current;
      return () => {
        clearInterval(intervalId);
      };
    }, []);
    

    【讨论】:

    • 谢谢!这就是我需要的。我很快放弃了 useRef,因为他们似乎主要将它用于文档中的组件,但我应该更仔细地阅读。再次感谢:)
    猜你喜欢
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 2015-07-23
    • 2023-02-25
    • 2021-12-20
    • 1970-01-01
    相关资源
    最近更新 更多