PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, August 5, 2022

[FIXED] How to correctly load data on WS event?

 August 05, 2022     axios, node.js, reactjs, redux, socket.io     No comments   

Issue

So. Server sends event to every client in specific room on message submit for other clients to load messages, so they can see that new message. React client correctly receives, but loads messages in weird way. It renders page with no messages and after few miliseconds loads correctly. It cause very ugly blink.

Client socket.io code:

useEffect(() => {
      loadRooms(userId).then(data => {
        dispatch(setRoomsList(data))
      })
      loadMessages(roomId).then(data => {
        dispatch(setMessageList(data))
      });

      socket.on('receive_message', data => {
        dispatch(addNewMessage({id: data.id, content: data.message, roomId: data.room, userName: data.userName}));
        console.log(messageList)
      })
    }, [dispatch, roomId, socket])

Client who sends message doesn't have this bug. On this client, axios request works correctly.

Submit message handler:

const handleMessageSubmit = e => {
      e.preventDefault()
      sendMessage(userName, currentMessage, roomId).then(data => {
        loadMessages(roomId).then(data => {
          dispatch(setMessageList(data))
          socket.emit('send_message', {message: currentMessage, room: roomId});
        })
        setCurrentMessage('')
      })
    }

Loading message normally with that handler work just fine, but with socket.io it is bugged.

How messages are displayed in page:

{messageList.map(message =>
                    <div sx={{overflow: 'auto'}} key={message.id} style={{display: 'block', width: '70vw', marginTop: '5px', clear: 'both'}}>
                      <div style={{wordWrap: 'break-word'}} key={message.id}>{message.userName}: {message.content}</div>
                    </div>
                  )}

messageList is redux state, which I get using mapStateToProps

Socket.io on the server side:

io.on('connection', (socket) => {
    let prevRoom = 1;
    console.log("Users's id", socket.id)
    
    socket.on('send_message', (data) => {
        socket.to(data.room).emit('receive_message', data.message)
        console.log("sent", data.message)
    })

    socket.on('join_room', (data) => {
        socket.leave(prevRoom)
        prevRoom = data;
        socket.join(data)
        console.log("joined")
    })
} )

Solution

The idea behind sending data through web sockets is that you read it from message that you receive and then render. You don't do that here. You ignore the data in "receive_message" and call "loadMessages" that, I assume, loads full messages list from api. This extra call to api causes the ugly blink, but the code that resets messageList is not in question (probably in redux).

You need to get rid of extra api call and append the new message received via web socket to your existing message list



Answered By - Marat
Answer Checked By - Terry (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing