I am using Socket.io and react to make a chat app. In this app i have already implemented messaging. For that i created a context state variable and whenever the state changes component renders with the latest message. I wanted to do the same to implement user-online feature. For this whenever a new user connects to server, it emits its id to all clients. For now i am simply emmiting a number 2 for simplicity.
On client side i am listening to this in a context provider file, which basically changes the state according to what server is sending.
I am using this state variable in the file below:
Now according to me, initially the state should be initiated with [], and when server sends id (i.e. 2 in this case) state variable should be changed to [2,] and all the children should be rerendered. As i am logging on console from ChatCard component, output should be first [] and then [2,], for each ChatCard Component. But for some reason, this is being logged out:
It is logging only []. This stays initially, but if any other thing in the app causes rerender, [2,] gets logged. Suggesting that state is not getting changed in the ChatCard component.
But if i use react dev tools to see the value of state provided by context.provider, it shows this:
This means that context is providing the latest state changes.
Even ChatCard shows that value of provided state is [2,]:
Please tell then why its not logging out [2,]
CodePudding user response:
You're mutating state which should be immutable.
In this image:
socket.on('online', id => {
setOnlineUsers((users) => {
users.push(id)
return users
})
})
It's mutating users
state. Causing React to not do a rerender. This StackOverflow post although old goes into it well.
What I would do is create a copy of users
, then mutate and return that. For example.
socket.on('online', id => {
setOnlineUsers((users) => {
const newUsers = users.slice()
newUsers.push(id)
return newUsers
})
})
This will cause state to be new and have React do a rerender showing the new array contents.