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

huangapple go评论64阅读模式
英文:

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

问题

我们正在在一个React应用中实现EventSource。我有一个可用的应用,但我想改进它。

我有两个问题:

  1. 我想在组件卸载之前传输完成时关闭连接。或者如果URL参数发生变化。

  2. 满足完整的依赖性检查规则。

现在我在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)

      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 关闭sse连接
    // sse.close()
  }
}, [companyDescription, projectDescription, showResults])

一个问题是,如果我将pushToDataArray添加到依赖数组中,它会陷入无限循环。另一个问题是,如果应用卸载,我无法访问sso对象以关闭连接。

有什么改进的想法吗?

也许sso可以存储为引用?

英文:

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?

答案1

得分: 0

Move soo out of the useEffect and make it a reference.

Implement pushToDataArray as a useReducer.

英文:

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

Implement pushToDataArray as a useReducer

huangapple
  • 本文由 发表于 2023年3月8日 19:08:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75672224.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定