TypeError: this.opts.wsEngine is not a constructor Socket.io MERN

Viewed 19

I want to add a small chatting feature in my mern app. I didn"nt want to watch a long course on it so I searched and found a blog on how to make a chat app with mern using socket.io.

MY BACKEND (server.js) file:

require("dotenv").config();
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const cors = require("cors");
const http = require("http");
const socketio = require("socket.io");
const { addUser, getAllUsers, getUser, removeUser } = require("./utils");
const app = express();
const port = process.env.PORT || 5000;

const server = http.createServer(app);

app.use(bodyParser.urlencoded({ extended: true }));

mongoose
  .connect(process.env.DATABASE_CONNECTION_STRING, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(() => {
    console.log("Connected to database");
  })
  .catch((error) => {
    console.log(error);
  });

app.use(express.json());

app.use(cors());
app.options("*", cors());


const io = socketio(server, { wsEngine: "ws" });

io.on("connection", (socket) => {
  socket.on("join", (data) => {
    const { name, room } = data;
    const { user, error } = addUser({ id: socket.id, name, room });

    if (error) return;
  });

  socket.emit("message", {
    user: "admin",
    text: `${user.name}, it's great to see you in here.`,
  });

  socket.broadcast.to(user.room).emit("message", {
    user: "admin",
    text: `${user.name} has just landed to the room.`,
  });

  socket.join(user.room);
  io.to(user.room).emit("room-data", {
    room: user.room,
    users: getAllUsers(user.room),
  });

  socket.on("left", () => {
    const user = removeUser(socket.id);
    user &&
      io.to(user.room).emit("message", {
        user: "admin",
        text: `${user.name} has just left `,
      });
  });

  socket.on("send-message", (message) => {
    const user = getUser(socket.id);
    io.to(user.room).emit("message", {
      user: user.name,
      text: message,
    });
    io.to(user.room).emit("room-data", {
      room: user.room,
      users: getAllUsers(user.room),
    });
  });
});

app.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

MY BACKEND (utills.js) folder:

let users = [];
const addUser = ({ id, name, room }) => {
  name = name.trim().toLowerCase();
  room = room.trim().toLowerCase();
  const userExists = users.find(
    (user) => user.name === name && user.room === room
  );
  if (!user || !room || userExists) return { error: "error" };
  const user = { id, name, room };
  users = [...users, user];
  return { user };
};

const removeUser = (id) => {
  const i = users.findIndex((user) => user.id === id);
  return i !== -1 ? users.splice(i, 1)[0] : null;
};

const getUser = (id) => users.filter((user) => user.id === id)[0];
const getAllUsers = (room) => users.filter((user) => user.room === room);
module.exports = { addUser, removeUser, getAllUsers, getUser };

MY FRONTEND my main(Chat.js) file:

import React, { useEffect, useState } from "react";
import { Box } from "@chakra-ui/react";
import io from "socket.io-client";
import { useSelector } from "react-redux";
import { useLocation } from "react-router-dom";
import { userChats } from "../../../../redux/ChatRequests";
import Info from "./Info";
import ChatVeiw from "./ChatVeiw";

const Chat = (name, room) => {
  let socket;
  const location = useLocation();
  const [users, setUsers] = useState([]);
  const [messages, setMessages] = useState([]);
  const auth = useSelector((state) => state.auth);
  const [chat, setChat] = useState([]);

  useEffect(() => {
    socket = io("http://localhost:5000/");
    socket.emit("join", { name, room });
    return () => {
      socket.emit("left");
      socket.off();
    };
  }, ["http://localhost:5000/", location.search]);

  useEffect(() => {
    socket.on("message", (message) => setMessages([...messages, message]));
    socket.on("room-data", ({ users }) => setUsers(users));
  });

  useEffect(() => {
    const getChats = async () => {
      try {
        const { data } = await userChats(auth._id);
        setChat(data);
        console.log(data);
      } catch (error) {
        console.log(error);
      }
    };
    getChats();
  }, [auth]);
  return (
    <Box pt={{ base: "130px", md: "80px", xl: "80px" }}>
      <main>
        <Info room={room} users={users} />
        <ChatVeiw messages={messages} name={name} room={room} />
      </main>
    </Box>
  );
};

export default Chat;

MY FRONTEND (ChatRequests.js) file:

import axios from "axios";


const API = axios.create({ baseURL: "http:localhost:5000" });

export const userChats = (id) => API.get(`/chat/${id}`);

MY FRONTEND (ChatVeiw.js) file:

import React from "react";
import ScrollToBottom from "react-scroll-to-bottom";
import { useForm } from "react-hook-form";

const ChatVeiw = ({ messages, name, room }) => {
  let socket;
  const { register, handleSubmit, reset } = useForm();

  const sendMessages = ({ message }) => {
    message && socket.emit("send-message", message);
    reset();
  };
  return (
    <section>
      <ScrollToBottom>
        {messages.map((message) => (
          <li>
            <span>{message.user}</span>
            <p>{message.text}</p>
          </li>
        ))}
      </ScrollToBottom>
      <form onSubmit={handleSubmit(sendMessages)}>
        <input type="text" {...register("message", { required: true })} />
        <button type="submit">Send</button>
      </form>
    </section>
  );
};

export default ChatVeiw;

MY FRONTEND my(Info.js):

const Info = ({ room, users }) => {
  return (
    <section>
      <header>
        <h2>{room}</h2>
      </header>
      <ul>
        {users.map((user) => (
          <li>{user}</li>
        ))}
      </ul>
    </section>
  );
};

export default Info;

The is also a form to enter your chat room:

import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";

const Form = () => {
  const { register, handleSubmit } = useForm();
  const navigate = useNavigate();

  const onSubmit = ({ name, room }) => {
    navigate(`/chat?name=${name}&room=${room}`);
  };
  return (
    <main className="form">
      <form onSubmit={handleSubmit(onSubmit)}>
        <input type="text" {...register("name", { required: true })} />
        <input type="text" {...register("room", { required: true })} />
        <button type="submit">Talk</button>
      </form>
    </main>
  );
};

export default Form;

I tried googling the answer and the closest I got was: https://github.com/socketio/socket.io/issues/3859

None of the suggestions worked for me.

I am using react to style my chat and he seem to be using vite.

Here is the 3 part blog I am reading:

PART 1: https://javascript.plainenglish.io/build-your-own-realtime-chat-app-with-mern-stack-c5908ba75126

PART 2: https://javascript.plainenglish.io/build-your-own-realtime-chat-app-with-mern-stack-f203af2e066e

PART 3: https://javascript.plainenglish.io/build-your-own-realtime-chat-app-with-mern-stack-1f2f0c022576

When I try to test my application I get an error of: TypeError: this.opts.wsEngine is not a constructor(In my backend server)

Please help me with problem. Thank you

0 Answers
Related