由于 Socket.io,反应上下文状态重置?
React context state resets because of Socket.io?
我查看了一些类似的线程,但其中 none 对此有修复。
当我点击一个频道时,它会将其设置为通过 setActiveChannel
,而 activeChannel
通过 ChannelContext
。一切正常,通道对象设置为此状态。但是当我通过 input => socket server => client 发送消息并执行 useEffect with [socket]
msgListener
cannot read activeChannel
object, it seems like it go back to default value of activeChannel
状态为 {}。
另一件有趣的事情是,例如,当我向文件添加新评论并保存它时,activeChannel
状态是应该的,if (msgData.channelId === activeChannel.channelId)
是真实的。但是当我刷新整个应用程序并开始“新鲜”首先打开频道然后输入消息时,msgListener
无法获得 activeChannel
.
import { ChannelContext } from "../../../context/channel";
import { socket } from "../../../context/socket";
export default function Chat() {
const { activeChannel } = useContext(ChannelContext);
const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState(null);
const classes = useStyles();
useEffect(() => {
console.log("Active channel changed");
console.log(activeChannel.channelId);
setCurrentState(activeChannel);
setMessages(activeChannel.messagesByDate);
}, [activeChannel]);
const msgListener = (msgData) => {
console.log("socket message before if: ");
console.log(msgData.message);
console.log("activechannel:");
console.log(activeChannel); // returns {}
console.log("activechannel id:");
console.log(activeChannel.channelId); //returns undefined
if (msgData.channelId === activeChannel.channelId) { // therefore not true
setNewMessage(msgData);
}
};
useEffect(() => {
if (socket) {
socket.on("message", msgListener);
return () => socket.off("message", msgListener);
}
}, [socket]);
...
}
这里是设置频道的代码:
const { activeChannel, setActiveChannel } = useContext(ChannelContext);
const getActiveChannel = async (channelId) => {
try {
const { data } = await axios.get(`/api/channel/${channelId}`, config);
if (data) {
setActiveChannel(data.channel);
}
} catch (error) {
return console.log(error.message);
}
};
此处父组件具有 Socket 上下文
const [activeChannel, setActiveChannel] = useState({});
return (
<div>
<ChannelContext.Provider value={{ activeChannel, setActiveChannel }}>
<SocketContext.Provider value={socket}>
<Dashboard channelItems={channelItems} getChannels={getChannels} />
</SocketContext.Provider>
</ChannelContext.Provider>
{error && <span>{error}</span>}
</div>
);
套接字上下文:
import { createContext } from "react";
import { io } from "socket.io-client";
export const socket = io();
export const SocketContext = createContext();
好的,知道了。我又写了socket useEffect:
useEffect(() => {
if (socket) {
socket.on("message", (msgData) => {
if (activeChannel.channelId) {
if (msgData.channelId === activeChannel.channelId) {
setNewMessage(msgData);
}
}
});
return () => socket.off("message");
}
}, [socket, messages]);
我查看了一些类似的线程,但其中 none 对此有修复。
当我点击一个频道时,它会将其设置为通过 setActiveChannel
,而 activeChannel
通过 ChannelContext
。一切正常,通道对象设置为此状态。但是当我通过 input => socket server => client 发送消息并执行 useEffect with [socket]
msgListener
cannot read activeChannel
object, it seems like it go back to default value of activeChannel
状态为 {}。
另一件有趣的事情是,例如,当我向文件添加新评论并保存它时,activeChannel
状态是应该的,if (msgData.channelId === activeChannel.channelId)
是真实的。但是当我刷新整个应用程序并开始“新鲜”首先打开频道然后输入消息时,msgListener
无法获得 activeChannel
.
import { ChannelContext } from "../../../context/channel";
import { socket } from "../../../context/socket";
export default function Chat() {
const { activeChannel } = useContext(ChannelContext);
const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState(null);
const classes = useStyles();
useEffect(() => {
console.log("Active channel changed");
console.log(activeChannel.channelId);
setCurrentState(activeChannel);
setMessages(activeChannel.messagesByDate);
}, [activeChannel]);
const msgListener = (msgData) => {
console.log("socket message before if: ");
console.log(msgData.message);
console.log("activechannel:");
console.log(activeChannel); // returns {}
console.log("activechannel id:");
console.log(activeChannel.channelId); //returns undefined
if (msgData.channelId === activeChannel.channelId) { // therefore not true
setNewMessage(msgData);
}
};
useEffect(() => {
if (socket) {
socket.on("message", msgListener);
return () => socket.off("message", msgListener);
}
}, [socket]);
...
}
这里是设置频道的代码:
const { activeChannel, setActiveChannel } = useContext(ChannelContext);
const getActiveChannel = async (channelId) => {
try {
const { data } = await axios.get(`/api/channel/${channelId}`, config);
if (data) {
setActiveChannel(data.channel);
}
} catch (error) {
return console.log(error.message);
}
};
此处父组件具有 Socket 上下文
const [activeChannel, setActiveChannel] = useState({});
return (
<div>
<ChannelContext.Provider value={{ activeChannel, setActiveChannel }}>
<SocketContext.Provider value={socket}>
<Dashboard channelItems={channelItems} getChannels={getChannels} />
</SocketContext.Provider>
</ChannelContext.Provider>
{error && <span>{error}</span>}
</div>
);
套接字上下文:
import { createContext } from "react";
import { io } from "socket.io-client";
export const socket = io();
export const SocketContext = createContext();
好的,知道了。我又写了socket useEffect:
useEffect(() => {
if (socket) {
socket.on("message", (msgData) => {
if (activeChannel.channelId) {
if (msgData.channelId === activeChannel.channelId) {
setNewMessage(msgData);
}
}
});
return () => socket.off("message");
}
}, [socket, messages]);