我正在尝试在React上使用SSE,一切都很顺利,但是组件没有重新渲染。
解决方案在下面
以下是代码:
import React, { useEffect, useState } from "react";
import axios from "axios";
function App() {
const [streamMessages, setStreamMessages] = useState([]);
const [eventSource, setEventSource] = useState(null);
const fetchData = async () => {
const msgs = await axios.get("http://localhost:3008/message/all/abc123");
setStreamMessages(msgs.data);
};
useEffect(() => {
fetchData();
setEventSource(new EventSource("http://localhost:3008/message/abc123"));
return () => {
if (eventSource) {
eventSource.close();
console.log("eventsource closed");
}
};
}, []);
useEffect(() => {
if (eventSource) {
eventSource.onopen = (event) => {
console.log("connection opened");
};
eventSource.onmessage = (event) => {
console.log("result", event.data);
setStreamMessages((old) => [...old, event.data]);
};
eventSource.onerror = (event) => {
console.log(event.target.readyState);
if (event.target.readyState === EventSource.CLOSED) {
console.log("eventsource closed (" + event.target.readyState + ")");
}
eventSource.close();
};
}
}, [eventSource, streamMessages]);
return (
<div className="App">
<input type="text" />
<button>Envoyer</button>
<div>
{streamMessages.map((message, index) => (
<p key={index}>
{message.message} <em>{message.createdAt}</em>
</p>
))}
</div>
</div>
);
}
export default App;
第一个 useEffect 用于获取“初始数据”并将其放入状态中。
const fetchData = async () => {
const msgs = await axios.get("http://localhost:3008/message/all/abc123");
setStreamMessages(msgs.data);
};
这个工作正常,我可以看到消息列表。
第二个 useEffect 应该会捕获传入的消息并将它们添加到初始消息数组中。
useEffect(() => {
if (eventSource) {
eventSource.onopen = (event) => {
console.log("connection opened");
};
eventSource.onmessage = (event) => {
console.log("result", event.data);
setStreamMessages((old) => [...old, event.data]);
};
eventSource.onerror = (event) => {
console.log(event.target.readyState);
if (event.target.readyState === EventSource.CLOSED) {
console.log("eventsource closed (" + event.target.readyState + ")");
}
eventSource.close();
};
}
}, [eventSource, streamMessages]);
我可以看到"console.log",这意味着事件被成功捕获,但我的消息列表'streamMessages'没有重新渲染。 我把这个状态'streamMessages'作为useEffect的依赖项。
我不知道代码哪里有问题
解决方案如下:
好的,我终于找到解决方案了。 我应用了Dennis Vash的一些修复(感谢您)。 但是主要的问题是我忘记对服务器发送的数据进行JSON解析。
以下是完整的、可工作的代码:
import React, { useEffect, useState } from "react";
import axios from "axios";
function App() {
const [streamMessages, setStreamMessages] = useState([]);
const [eventSource, setEventSource] = useState(
() => new EventSource("http://localhost:3008/message/abc123")
);
useEffect(() => {
const fetchData = async () => {
const msgs = await axios.get("http://localhost:3008/message/all/abc123");
setStreamMessages(msgs.data);
};
fetchData();
return () => {
if (eventSource) {
eventSource.close();
console.log("eventsource closed");
}
};
}, []);
useEffect(() => {
if (eventSource) {
eventSource.onopen = (event) => {
console.log("connection opened");
};
eventSource.onmessage = (event) => {
setStreamMessages((old) => [...old, JSON.parse(event.data)]);
};
eventSource.onerror = (event) => {
console.log(event.target.readyState);
if (event.target.readyState === EventSource.CLOSED) {
console.log("eventsource closed (" + event.target.readyState + ")");
}
eventSource.close();
};
}
}, [eventSource, streamMessages]);
return (
<div className="App">
<input type="text" />
<button>Envoyer</button>
<div>
{streamMessages.map((message, index) => (
<p key={index}>
{message.message} <em>{message.createdAt}</em>
</p>
))}
</div>
</div>
);
}
export default App;