export const Component = () => {
const [messages, setMessages] = useState([]);
const sendMessage = msg => {
socket.emit('message', msg);
setMessages([
...messages,
{
content: msg.content
}
])
};
const onMessage = msg => setMessages([
...messages,
{
content: msg.content
}
]);
useEffect(() => {
socket.on('message', onMessage)
}, []);
return (
<button onClick={() => sendMessage({content: 'test'})}/>
)
};
这是我如何实现发送/获取消息的示例代码。问题在于,如果我从套接字(Onmessage(收到消息,始终会恢复消息。一切都很好,如果我通过sendMessage
函数进行操作,则消息正在填充。
谢谢!
编辑:我已经解决了这个问题,有答案:
useEffect(() => {
socket.on('message', onMessage)
}, [messages]); //rerender if messages changed
,但我不明白为什么这能解决我的问题。有人可以解释吗?
编辑2:
useEffect(() => {
socket.on('message', onMessage)
return () => {
socket.off('message', onMessage);
}
}, [messages]); //rerender if messages changed
您如何看待此解决方案?
您的问题是closure
的简单情况。当您在初始加载期间将事件侦听器方法设置为套接字时,onMessage
甚至使用其词汇范围。但是,在接下来的下一篇后续渲染过程中,创建了一个新的Onmessage,其更新的词汇范围并未将其重新分配给socket event
,因此它引用了最初加载期间存在的messages
值。
但是,如果您写下效果以执行每个消息更改,则在消息更改重新渲染上创建的新的Onmessage方法正在分配给套接字事件,并且可以正常工作。
但是,比使用messages
作为useEffect
中的依赖性更好的解决方案是使用状态更新回调
const onMessage = msg => setMessages(prevMessages => ([
...prevMessages,
{
content: msg.content
}
]));
useEffect(() => {
socket.on('message', onMessage)
return () => {
socket.off('message', onMessage);
}
}, []);