2

I have a bit of experience with react and express. I am trying to build a chat app using socket io. I am first time using it. But I think I got it a little bit after reading some documentation and youtube videos. Now, when someone enters the same room they can communicate. Now, suppose I am already in the room and someone joins the room then I suppose to see that person joined the room and I successfully turned it into logic and it worked. But, when I enter the room I want to show the message to myself that "You entered the room" where others will see "myname entered the room". I put the logic but somehow it is not working. I tried chatgpt but I ended up making him understand the logic :/

I have parent component called App and two children components called Join that is the form to join the room and another Message component that is the message body. I take the inputs(name, room) from Join to parent app and pass them as props to Message. This is my state of the Message component -->

this.state = {
      messages: [],
      inputMessage: "",
      joinedName: "",
      joinedRoom: "",
    };

and this is the componentDidMount lifecycle to change the state whenever a person sends and message or joins the room -->

componentDidMount() {
    const { room, name } = this.props;
    this.props.socket.emit("join-room", { room, name });
    this.props.socket.on("joined-room", (receivedName) => {
      this.setState({
        joinedName: receivedName,
        joinedRoom: receivedName === name ? "me" : "other",
      });
    });

    this.props.socket.on("receive-message", (newMessage) => {
      this.setState((prevState) => ({
        messages: [...prevState.messages, { content: newMessage, sender: "other" }],
      }));
    });
  }

To understand more here is the relevant part of my server -->

socket.on("join-room", (data) => {
        socket.join(data.room);
        socket.to(data.room).emit("joined-room",data.name)
    })

As you can see I am sending the name and room whenever a person joins the room. And changing the state accordingly and I am checking if the name I received from server is the name I provided earlier from the props or not. If it is then joinedRoom is me otherwise other. Then later I am using the joinedRoom state to show whether me or others entered the room. Here is how -->

{joinedName && (
            <div
              className={`bg-light-gray br3 rounded-lg pa2 mb2 self-end`}
              style={{
                color: "#fff",
                background: "rgb(148, 61, 255)",
              }}
            >
              <p className="ma0">
                {joinedRoom === "me" ? "You" : joinedName} joined the room
              </p>
            </div>
          )};

Then I am rendering this div if anyone joined the room. And I am checking in the p tag whether it is me or not and rendering the p tag accordingly as you can see.

Now the problem is when I join the room I am not seeing that "You joined the room" div. But when others enter the room I can see that "theriname entered the room". What is the flaw here?

2 Answers2

0

can you give us a working code in codesandbox.io ? Meanwhile, can you check if

socket.on("join-room", (data) => {
        socket.join(data.room);
        socket.to(data.room).emit("joined-room",data.name)
    })

in this block, you are getting data.room and data.name properly for both the cases? (you/other joining)

koushik deb
  • 158
  • 10
  • I console logged to check and it is working. When me/other joins a room I get the room and name of the user in my server. But the issue lies in the front-end. I console logged the recievedName inside the componenDidMount hook inside the joined-room socket. When I join the room, I don't get my name on the console. But when I am already in a room and someone joins the same room I get their name in the console. So, I think the issue is with the lifecycle or related to react specific. It looks like the joined-room socket inside componentDidMount is not running the first time when I join the room. – Nabil Ahmed Jul 05 '23 at 16:42
  • Hey, got it. Can you make a sample in codesandbox? I would really like to investigate it. Thanks – koushik deb Jul 05 '23 at 16:43
  • I mean to deploy the app? Or what? – Nabil Ahmed Jul 05 '23 at 16:45
  • No no. In codesandbox you can create sample react app with just the existing issue you are dealing with. (Sometimes it might not be possible if the issue is spread throughout the project) in your case, it might be like that. So, if you can't create a sample, it is ok. Hopefully you will find the solution soon. – koushik deb Jul 05 '23 at 17:01
  • Ok, I am creating the sample react app with just the front-end code. What about the backend how will you get the backend? – Nabil Ahmed Jul 05 '23 at 17:09
  • Demo response object of backend would be enough, i think – koushik deb Jul 05 '23 at 17:27
  • https://codesandbox.io/p/sandbox/inspiring-bohr-ww5xvg Here is the sample code front-end. I also added the backend in a text file. – Nabil Ahmed Jul 05 '23 at 17:30
0

I solved the problem and I am posting the answer here so that in case someone else faces this they don't have to struggle like me. In my server I was sending the joined person's name in the joined-room socket to everyone in the room except the very person who joined the room by coding this line

socket.to(data.room).emit("joined-room",data.name)

This is a socket.io thing that it sends the corresponding data to everyone in the room except the person who sent it in the firsthand. To send it to all including the sender the code would be this

io.to(data.room).emit("joined-room",data.name)

This will send the data to everyone in the room including the sender himself :)