В вашем примере у вас есть две вещи: 1) setTimeout делает закрытие для вашей переменной messages
(и именно поэтому вы видите {}
) 2) Когда вы используете setMessages({a: 1})
, вы удаляете все остальные поля из messages
состояние
Итак, ваш код будет выполняться в следующем порядке (код, в котором выделены проблемы):
function GroupProvider(props){
const socket = useMemo(()=> io(url), [socket]);
const [messages, setMessages] = useState({});
const setMessage = (message, room) => {
// message = Hi dear, How are you, room: roomid100
// messages: {}
if (messages[room] !== undefined){
setMessages({ [room]: [message, ...messages[room]] });
}
else{
// Problem 1: Here you remove all other changes from you state
setMessages({ [room]: [message] }); // updating messages per room
}
// Problem 2: Here you have a closure to your `messages` variable, so that it will be {}
console.log('room: ', room); // I get the value: roomid100
console.log('message: ', message); // I get the message: Hi dear, How are you
setTimeout(() => {
console.log('messages: ', messages); // But here always I get empty {}
}, 2000);
}
return (
<GroupContext.Provider value={{socket, messages, setMessage}}>
{props.children}
</GroupContext.Provider>
);
}
Таким образом, вы можете исправить это с помощью useEffect, чтобы вы могли проверить свою переменнуюв правильном пути.И я предлагаю вам использовать setMessages
как функцию, чтобы упростить ваш код:
function GroupProvider(props) {
const socket = useMemo(() => io(url), [socket]);
const [messages, setMessages] = useState({});
const setMessage = (message, room) => {
setMessages((messages) => {
if (messages[room] !== undefined) {
return { ...messages, [room]: [message, ...messages[room]] };
}
return { ...messages, [room]: [message] };
});
};
// we will console log, when `messages` state changes
useEffect(
() => {
console.log('messages: ', messages);
},
[messages]
);
return <GroupContext.Provider value={{ socket, messages, setMessage }}>{props.children}</GroupContext.Provider>;
}