我有一些像下面这样的反应组件。我可以使用“消息”作为回报,但是如果我尝试访问某个函数或 useEffect 中的消息,例如,我总是成为初始值。如何在功能组件中解决它?谢谢
const Messages = () => {
const { websocket } = useContext(WebsocketsContext);
let [ messages, setMessages ] = useState([]);
useEffect(() => {
getMessages()
.then(result => {
setMessages(result);
})
}, []);
useEffect(() => {
if(websocket != null){
websocket.onmessage = (msg) => {
let wsData = JSON.parse(msg.data);
if(wsData.message_type == 'Refresh'){
console.log(messages)
};
};
};
}, [websocket]);
return(
<div>...</div>
);
};
export default Messages;
答案 0 :(得分:2)
看起来您遇到了stale closure
在其依赖数组中带有 [websockets]
的 useEffect 只会在 websocket 引用/值更改时“更新”。无论何时,该函数都会在那个时间点在 messages
周围创建一个“闭包”。因此,消息的值将保持在该闭包内。如果消息在 websocket 创建后更新,它将永远不会更新 onmessage 回调函数中“消息”的值。
要解决此问题,请将“消息”添加到依赖项数组。 [websockets, messages]
。这将确保 useEffect 回调始终具有最新的消息状态,并且 onmessage 函数将具有最新的消息状态。
useEffect(() => {
if(websocket != null){
websocket.onmessage = (msg) => {
let wsData = JSON.parse(msg.data);
if(wsData.message_type == 'Refresh'){
console.log(messages)
};
};
};
}, [websocket, messages]);
答案 1 :(得分:1)
这是因为您的 getMessages()
是一个异步函数。顺序如下:组件最初安装并初始化值 -> componentDidMount() 被调用意味着你的 getMessages()
被调用(一个异步函数!) -> 你的 webaocket
被初始化并调用第二个 { {1}},它读取 useEffect
的初始值 -> 您的 messages
获得其响应并相应地设置 getMessages
。
要使其按预期工作,请将第二个 messages
的依赖项数组设为 useEffect
。