在useEffect中反应功能组件访问状态
React functional component access state in useeffect
我有一些像下面这样的反应组件。我可以在 return 中使用“消息”,但是如果我尝试在某些函数或 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;
看来你遇到了stale closure
只要 websocket reference/value 发生变化,其依赖数组中带有 [websockets]
的 useEffect 只会“更新”。无论何时,该函数都会在那个时间点围绕 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]);
因为你的getMessages()
是一个异步函数。顺序如下:组件最初安装并初始化值 -> componentDidMount() 被调用意味着你的 getMessages()
被调用(一个异步函数!) -> 你的 webaocket
被初始化并调用第二个 useEffect
,它读取 messages
的初始值 -> 你的 getMessages
得到它的响应并相应地设置 messages
。
要使其按预期工作,请将第二个 useEffect
的依赖项数组设为 [websocket, messages]
。
我有一些像下面这样的反应组件。我可以在 return 中使用“消息”,但是如果我尝试在某些函数或 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;
看来你遇到了stale closure
只要 websocket reference/value 发生变化,其依赖数组中带有 [websockets]
的 useEffect 只会“更新”。无论何时,该函数都会在那个时间点围绕 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]);
因为你的getMessages()
是一个异步函数。顺序如下:组件最初安装并初始化值 -> componentDidMount() 被调用意味着你的 getMessages()
被调用(一个异步函数!) -> 你的 webaocket
被初始化并调用第二个 useEffect
,它读取 messages
的初始值 -> 你的 getMessages
得到它的响应并相应地设置 messages
。
要使其按预期工作,请将第二个 useEffect
的依赖项数组设为 [websocket, messages]
。