Search code examples
reactjsuse-effectuse-stateuse-ref

useEffect with a dependency that changes too fast


Here's the problem:

function Foo(){
  let [events, setEvents] = useState([])

  useEffect(() => {
    let subscription = client.subscribe("eventType", event => {
      setEvents([...events, event])
    })
    return () => subscription.unsubscribe()
  }, [events])
}

So here if I make events a useEffect dependency it will unsubscribe / subscribe every time an event is added, and I will miss some. I can make events a ref, but then it won't re-render.

What's the right way to do this?

Edit: From the comments / answers I've gotten so far there seems to be no good way to deal with this in React. I have an ugly setInterval solution that I will post as an answer if nobody comes up with something better within 2 days.

EDIT 2: Here's a codesandbox showing the issue with setInterval. I'm looking for a solution that doesn't require events as a dependency (removing events dependency is not a solution, obviously.)


Solution

  • Instead of grabbing events from outside the useEffect, you can just pass a callback to setEvents that will receive the current value for events:

    function Foo(){
        let [events, setEvents] = useState([])
    
        useEffect(() => {
            let subscription = client.subscribe("eventType", event => {
                setEvents((previousEvents) => [...previousEvents, event])
            })
            return () => subscription.unsubscribe()
        }, []) // no need to add `events` to dependencies because we're getting it from `setEvent`'s callback
    }