gpt4 book ai didi

reactjs - React UseEffect setState 不会重新渲染

转载 作者:行者123 更新时间:2023-12-05 06:47:32 32 4
gpt4 key购买 nike

我正在 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;

首先使用Effect获取'初始数据'并将它们放入状态

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;

最佳答案

不能保证它能正常工作,因为服务器上可能存在错误(没有可重现的示例)。

所以我修正了一些错误,有两个片段,一个有效,并且有错误评论。

固定:

function App() {
const [streamMessages, setStreamMessages] = useState([]);
const [eventSource, setEventSource] = useState(
() => new EventSource("http://localhost:3008/message/abc123")
);

// Fetch data init
useEffect(() => {
const fetchData = async () => {
const msgs = await axios.get("http://localhost:3008/message/all/abc123");
setStreamMessages(msgs.data);
};

fetchData();
}, []);

// Eventsource setup
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]);

return <>...</>;
}

评论中的错误(至少我认为那些是错误的):

function App() {
const [streamMessages, setStreamMessages] = useState([]);
const [eventSource, setEventSource] = useState(null);

// should be in scope of useEffect callback
// not a mistake in this case, but usually has a closure on some stale data
const fetchData = async () => {
const msgs = await axios.get("http://localhost:3008/message/all/abc123");
setStreamMessages(msgs.data);
};

useEffect(() => {
fetchData();

// unnecessary render, should be as initial value
setEventSource(new EventSource("http://localhost:3008/message/abc123"));

return () => {
// closure on eventSource == null value
// Should get lint warning here
if (eventSource) {
eventSource.close();
console.log("eventsource closed");
}
};
}, []);

useEffect(() => {
// always truthy on streamMessages change
// therefore will reinit on every streamMessages render

// should run only once
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();
};
}
// mistake, no need streamMessages in dep array
// should get lint warning here
}, [eventSource, streamMessages]);

return <>...</>;
}

关于reactjs - React UseEffect setState 不会重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67087245/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com