Home > Blockchain >  Context not passing latest value of state - React
Context not passing latest value of state - React

Time:10-26

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.

Server

On client side i am listening to this in a context provider file, which basically changes the state according to what server is sending.

enter image description here Context Provider File

I am using this state variable in the file below: File where state is used

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: Output on console

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: enter image description here

This means that context is providing the latest state changes.

Even ChatCard shows that value of provided state is [2,]:

enter image description here

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.

  • Related