Search code examples
reactjsreact-hookseslintserver-sent-events

How to Implement EventSource with dynamic url parameters in React, satisfying exhautive deps and avoid render loop


We are implementing EventSource in a React app. I have a working app, but I would like to improve it.

Two issues I have are:

I would like to close the connection if the component unmounts before the transmission is done. Or if the url parameters change.

And satisfying the exhaustive deps linting rule.

Now I establish the connection in a useEffect:

    useEffect(() => {
    if (showResults) {
      const sse = new EventSource(
        `${AI_API_BASE_URL}?param1=${param1}&param2=${param2}`
      )
      sse.addEventListener("event", (e) => {
        const parsedData = JSON.parse(e.data, (key, value) => {
          if (key === "id") {
            return parseInt(value, 10)
          }
          return value
        })
        
          pushToDataArray(parsedData)
        
        } else if (parsedData.isdone === true) {
          setNumberOfTries((numberOfTries) => ({
            count: numberOfTries.count + 1,
            timestamp: Date.now(),
          }))
          setErrors([])
          sse.close()
        }
      })
      sse.onerror = (e) => {
        console.log("error", e)
        setErrors((errors) => [...errors, e])
      }
    }

    return () => {
      // TODO close sse connection
      //sse.close()
    }
  }, [companyDescription, projectDescription, showResults])

One issue is that if I add pushToDataArray to the dependency array, it goes into an infinite loop. The other issue is that I can't close the connection if it unloads because I can't reach the sso-object.

Any ideas for improvements?

Maybe the sso could be stored as a reference?


Solution

  • Move soo out of the useffect and make it a reference.

    Implement pushToDataArray as a useReducer