Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am creating a simple popup window component for my website and I want to periodically gather any new or incoming messages about every second or so for live messaging functionality. I am currently using react for my project.

My main problem is, I only want to gather messages when a prop called "active" is set to True, and I can't figure out how to do so.

Here is a mockup of my web page that could hopefully help. It is of a mockup of the webpage and has three entries, one with an open messaging window.

I have multiple entries that can have their messaging window open, but I've passed other props down so that only one messaging window can be open at a time. So it is possible to have an interval / timer thing in one of the component's ancestors instead, but I wanted to make this popup window more self-sufficient with its own call to the API.

I've tried using a setInterval function that initializes in a useEffect function inside the messaging window component:

    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])

However, as the comment points out, I can't actually clear the interval because I can't find a way to make the interval handle my_interval stable enough (useRef doesn't work)

I also tried using a timeout function with a recursive call that will keep calling itself as long as active is true, but I think I have a similar issue in that the function itself is changing and so the recursive call is kind of broken.

    // 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);
    }, [])

Any help or different strategies would be much appreciated, I really want my messenger popup to be self-sufficient with its own call to my RestAPI but it almost seems impossible at this point.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
231 views
Welcome To Ask or Share your Answers For Others

1 Answer

useRef is an object, see docs of its 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);
  };
}, []);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...