javascript - 停止使用在反应应用程序中重新订阅的事件源
问题描述
我有一个简单的例子,包括一个服务器发送事件服务器每 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;
解决方案
事实证明它比我最初想的要复杂得多,所以我没有重新发明轮子,而是找到了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
变量只是从服务器接收到的最新消息。
推荐阅读
- android - 将什么传递给 Intent 构造函数以获得 geric 方法?
- mongodb - 如何在mongo的中间聚合阶段计算根文档的数量?
- c# - 如何避免重复的属性声明。在 C# 类中
- java - 将 Apache Solr 6.x 升级到 7.x Tokenizer 和 Criteria 多个值
- javascript - 使用 addEventListener
- docusignapi - 无法在我的 DocuSign 帐户下添加 API 集成密钥
- javascript - 如何在弹出窗口中显示错误消息
- flutter - Flutter While 功能未按要求执行
- crystal-reports - 水晶报表:参数损坏整个报表
- java - 获取 java.lang.IllegalArgumentException “名称不能为空!” 更新 MongoDB 集合时