首页 > 解决方案 > 停止使用在反应应用程序中重新订阅的事件源

问题描述

我有一个简单的例子,包括一个服务器发送事件服务器每 5 秒发送一次更新,以及一个监听它的反应应用程序。每次useEffect调用 react 应用程序似乎都会添加一个新的侦听器,同时保留旧的侦听器,这显然会使应用程序很快崩溃。

我尝试添加一个侦听状态变量,并且仅在未侦听时才进行订阅,并且仅useEffect在页面首次加载时触发。在这些情况下,数据将停止正确更新。

服务器.js

const http = require("http");

http
  .createServer((request, response) => {
    console.log("Requested url: " + request.url);

    if (request.url.toLowerCase() === "/events") {
      response.writeHead(200, {
        Connection: "keep-alive",
        "Content-Type": "text/event-stream",
        "Cache-Control": "no-cache",
        "Access-Control-Allow-Origin": "*"
      });

      setInterval(() => {
        console.log('interval')
        response.write("event: scan\n");
        response.write("\n\n");
      }, 5000);
    }

  })
  .listen(5000, () => {
    console.log("Server running at http://127.0.0.1:5000/");
  });

应用程序.js

import React, { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [data, setData] = useState([0])
  const [eventSource, setEventSource] = useState(new EventSource("http://127.0.0.1:5000/events"));

  useEffect(() => {
    console.log('render')
    eventSource.addEventListener('scan', event => {
      setData([data[0] + 1, ...data]);
    });

  }, [data]);

  return (
    <div> { data } </div>
  );
}

export default App;

标签: javascriptreactjsserver-sent-events

解决方案


事实证明它比我最初想的要复杂得多,所以我没有重新发明轮子,而是找到了react-hooks-sse包。然后解决方案如下所示:

import React, { useState, useEffect } from 'react';
import { useSSE, SSEProvider } from 'react-hooks-sse';

import './App.css';


const Component = () => {
  const state = useSSE('scan');
  const [data, setData] = useState([])

  useEffect(() =>{
    if (state) {
    setData([state.data.some.value ,...data]);
  }

}, [state])

return data
}

function App() {

  return (
    <SSEProvider endpoint="http://127.0.0.1:5000/events" >
        <Component />
    </SSEProvider>
);
}

export default App;

从技术上讲,该state变量只是从服务器接收到的最新消息。


推荐阅读