skip to Main Content

I am creating a real time chat application, where users can chat with other users in real time. All users are stored in my MongoDB Database. I’m using React on the frontend, and node with express on the backend.

When users connect to the socket server, they’re added to the users array stored on the server, like so:

var users = [
   // User objects
   {username: test1, id: 32d2, socketId: ue3e9393kd3},
   {username: test2, id: 322, socketId: ude3e339393kd3},
   {username: test3, id: 333dw2, socketId: ud33e9393kd3},
]

On the frontend, when chatting with a user, they first select the other users name from a messages list, and it redirects to the route chat/otheruserid. So whatever user they want to chat with, the other users id would be stored in the url.

When submitting the message to send, it is received by the server and sent back to the client. I currently use the following code to send message events.

io.to(user.socketId).emit('send message', msg)

This socket id would be obtained by filtering the users array to find a specific user (i.e the one they selected on the frontend to chat with)

The problem I have, is if using the example above, if the user test1 had a chat with test2, and a chat with test3, if both test2 and test3 sent a message to user test1, how would I be able to append the message to the DOM of the correct chat screen.

For example, if test2 and test3 send messages to test1 at approximately the same time, and test1 was on the chat page with test2, then you could append the message from test2 to the current page’s DOM. However if when on the chat page with test2, and test3 sends a message, how would I append the message from test3 to the chat screen located at the path: chat/test3id, so when the user eventually goes to this path, the new message has been appended to the dom? Thanks.

2

Answers


  1. @Sam I think, you need a way to associate the incoming msgs with the correct chat screen on the frontend. One good approach is to use target user’s id when sending msg from the server to the client.

    I can show you a simplified example.

    • server side
    // Assuming user is the sender and targetUserId is the id of the user they are chatting with
    io.to(targetUserSocketId).emit('send message', { senderId: user.id, message: msg });
    
    • client side
    // Assume you have a state variable to keep track of the currently open chat screen
    const [currentChatUserId, setCurrentChatUserId] = useState(null);
    
    // Handle the 'send message' event
    socket.on('send message', ({ senderId, message }) => {
      if (senderId === currentChatUserId) {
        // Append the message to the DOM of the currently open chat screen
        // You can use your own logic to update the chat messages in the state
        // or trigger a re-fetch of messages for the open chat screen
      } else {
        // Store the message for later use (e.g., in a Redux store or component state)
        // This way, when the user navigates to the chat screen with the senderId,
        // you can retrieve and display the stored messages
      }
    });
    
    // Update the currentChatUserId when the user navigates to a different chat screen
    const handleChatNavigation = (userId) => {
      setCurrentChatUserId(userId);
      // Fetch messages for the selected chat screen or load stored messages
    };
    

    Hope to be helpful for your understanding.

    Login or Signup to reply.
  2. I recoded to send you more brief example, with the variable names on your explanation of scenario, namely test1,2,3.

    • server side
    // Assuming user is the sender (e.g., test2) and targetUserId is the id of the user they are chatting with (e.g., test1)
    io.to(test1SocketId).emit('send message', { senderId: test2.id, message: msg });
    
    • client side
    import React, { useState, useEffect } from 'react';
    
    // Assume you have a state variable to keep track of the currently open chat screen
    const ChatComponent = () => {
      const [currentChatUserId, setCurrentChatUserId] = useState(null);
      const [messages, setMessages] = useState([]);
    
      // Handle the 'send message' event
      useEffect(() => {
        const handleSendMessage = ({ senderId, message }) => {
          if (senderId === currentChatUserId) {
            // Append the message to the DOM of the currently open chat screen
            // You can use your own logic to update the chat messages in the state
            setMessages((prevMessages) => [...prevMessages, message]);
          } else {
            // Store the message for later use (e.g., in a Redux store or component state)
            // This way, when the user navigates to the chat screen with the senderId,
            // you can retrieve and display the stored messages
            // You might want to implement your own logic to handle message storage
          }
        };
    
        // Replace 'socket' with your actual socket instance
        socket.on('send message', handleSendMessage);
    
        return () => {
          // Clean up the event listener when the component unmounts
          socket.off('send message', handleSendMessage);
        };
      }, [currentChatUserId]);
    
      // Update the currentChatUserId when the user navigates to a different chat screen
      const handleChatNavigation = (userId) => {
        setCurrentChatUserId(userId);
        // Fetch messages for the selected chat screen or load stored messages
        // You might want to implement your own logic for fetching messages
      };
    
      return (
        <div>
          {/* Render your chat UI and append messages from the 'messages' state */}
          <h2>Chatting with {currentChatUserId}</h2>
          {/* Your chat messages UI */}
          {messages.map((message, index) => (
            <div key={index}>{message}</div>
          ))}
          {/* Your chat navigation UI */}
          <button onClick={() => handleChatNavigation('test1')}>Chat with test1</button>
          <button onClick={() => handleChatNavigation('test3')}>Chat with test3</button>
        </div>
      );
    };
    
    export default ChatComponent;
    

    Hope to be more helpful.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search