How to reconnect socket instance from Socket.io after page refresh on React page?

Viewed 167

Trying to make a simple chat app with express + socket.io and react but this issue has been racking my brain. Whenever I refresh the page on messaging app route, I can't send any messages. I tried circumventing that by using react-router with the history API to send me back to homepage. However, when I'm routed back to the homepage, I can't re-enter into the chat page unless I refresh again on the homepage. It seems that the socket object is null whenever I refresh the page.

Server Code:

const room = "general";
const room2 = "memes";

const LOGIN = "loginEvent";
const NEW_MESSAGE_EVENT = "newMessageEvent";
const LEAVE_EVENT = "leaveEvent";

io.on("connection", (socket) => {
  socket.on(LOGIN, ({ nickname, room }, callback) => {
    const user = addUser(socket.id, nickname, room);
    socket.join(user.room);
    callback();
    // socket.emit()
  });

  socket.on(NEW_MESSAGE_EVENT, (data) => {
    console.log(data);
    io.in(room).emit(NEW_MESSAGE_EVENT, data);
  });

  socket.on("disconnect", () => {
    const deletedUser = delUser(socket.id);
    console.log("User deleted:", deletedUser);
    if (deletedUser) {
      io.in(room).emit(LEAVE_EVENT, {
        notification: `User ${deletedUser.nickname} has just left`,
      });
    }
    socket.leave(room);
  });
});

In my client-side, I use the react context API to store the socket object like so:

  
import React, { createContext } from "react";
import io from "socket.io-client";

const SocketContext = createContext();

const SocketProvider = ({ children }) => {
  const ENDPOINT = "http://localhost:3030";
  const socket = io(ENDPOINT);
  return (
    <SocketContext.Provider value={socket}>
      {children}
    </SocketContext.Provider>
  );
};

export { SocketContext, SocketProvider };

Then, I create a hook to send messages:

import { useState, useContext, useEffect } from "react";
import { SocketContext } from "../contexts/socketContext";

const NEW_MESSAGE_EVENT = "newMessageEvent";

const useRoom = () => {
  const socket = useContext(SocketContext);
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    socket.on(NEW_MESSAGE_EVENT, (message) => {
      const incomingMessage = {
        ...message,
        isOwner: message.id === socket.id,
      };
      setMessages((messages) => [...messages, incomingMessage]);
    });
    return () => {
      socket.close();
    };
  }, [socket]);

  const sendMessage = (message) => {
    socket.emit(NEW_MESSAGE_EVENT, { body: message, id: socket.id });
  };

  return { messages, sendMessage };
};

export default useRoom;
0 Answers
Related