I've gote some react component like below. I can use "messages" in return, but if I try to access messages inside some function, or useEffect, as in example, I always become initial value. How can I solve it in functional component? Thanks
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;
Looks like you have encountered a stale closure
the useEffect with [websockets]
in its dependency array will only ever "update" whenever the websocket reference/value changes. Whenever it does, the function will have created a "closure" around messages
at that point in time. Thus, the value of messages will stay as is within that closure. If messages updates after websocket has been created, it will never update the value of "messages" within the onmessage callback function.
To fix this, add "messages" to the dependency array. [websockets, messages]
. This will ensure the useEffect callback always has the latest state of messages, and this the onmessage function will have the latest state of messages.
useEffect(() => {
if(websocket != null){
websocket.onmessage = (msg) => {
let wsData = JSON.parse(msg.data);
if(wsData.message_type == 'Refresh'){
console.log(messages)
};
};
};
}, [websocket, messages]);