Coder Social home page Coder Social logo

mern-chat-app's Introduction

MERN Stack Project: Build and Deploy a Real Time Chat App | JWT, Socket.io

Demo App

Video Tutorial on Youtube

Some Features:

  • ๐ŸŒŸ Tech stack: MERN + Socket.io + TailwindCSS + Daisy UI
  • ๐ŸŽƒ Authentication && Authorization with JWT
  • ๐Ÿ‘พ Real-time messaging with Socket.io
  • ๐Ÿš€ Online user status (Socket.io and React Context)
  • ๐Ÿ‘Œ Global state management with Zustand
  • ๐Ÿž Error handling both on the server and on the client
  • โญ At the end Deployment like a pro for FREE!
  • โณ And much more!

Setup .env file

PORT=...
MONGO_DB_URI=...
JWT_SECRET=...
NODE_ENV=...

Build the app

npm run build

Start the app

npm start

mern-chat-app's People

Contributors

burakorkmez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mern-chat-app's Issues

npm start issue

when we connect to the frontend to backend port it not showing the background image
Uploading Screenshot 2024-05-28 102904.pngโ€ฆ

Error in send Message Route TypeError: getReceiverSocketId is not a function

Error in send Message Route TypeError: getReceiverSocketId is not a function

const Conversation = require("../models/conversation.models");
const Message = require("../models/message.models");
const { io } = require("../app");
const getReceiverSocketId = require("../app").getReceiverSocketId;

const sendMessage = async(req,res)=>{
// console.log("messages",req.params.id);

try {
    const {message} = req.body;
    const receiverId = req.params.id;
    const senderId = req.user._id;
    console.log(`Sender: ${senderId}, Receiver: ${receiverId},, Message" ${message}`);

    let conversation = await Conversation.findOne({
        participants: { $all : [senderId, receiverId]}
    })

    //send 1st time
    if(!conversation){
        conversation = await Conversation.create({
            participants: [senderId,receiverId],
        })
    }

    const newMessage = new Message({
        senderId,
        receiverId,
        message
    })
    
    if(newMessage){
        conversation.messages.push(newMessage._id);

    }
     // await conversation.save();
    // await newMessage.save();
    //optimize the upper 2 line
    await Promise.all([conversation.save(), newMessage.save()])//this will run in parallel


    //Socket IO
    const receiverSocketId = getReceiverSocketId(receiverId);

	if (receiverSocketId) {
		// io.to(<socket_id>).emit() used to send events to specific client
		io.to(receiverSocketId).emit("newMessage", newMessage);
	}

    // console.log("newMessage", newMessage);
    res.status(201).json(newMessage)

    
} catch (error) {
    console.log("Error in send Message Route", error);
    res.status(500).send({
        success:false,
        message: error.message
    })
}

}

const getMessage = async(req,res)=>{
try {
const userToChatId = req.params.id;
const senderId = req.user._id;

    const conversation = await Conversation .findOne({
        participants:{$all : [senderId,userToChatId]},
    }).populate("messages")//not ref but actual message

    if(!conversation){
        return res.status(200).send({
            success:true,
            message: [],
        })
    }
    
    const messages  = conversation.messages
    res.status(200).send({
        success:true,
        message: messages
    })
} catch (error) {
    console.log("Error in Get Message Route", error);
    res.status(500).send({
        success:false,
        message: error.message
    })
}       

}

module.exports = {sendMessage,getMessage}

Thank You for everything!

Hey @burakorkmez!

My sincere gratitude for the incredibly detailed and informative video tutorial you provided. Your clear explanations and step-by-step guidance made it much easier for me to understand the concepts and implement them effectively.

I was wondering if you could provide some guidance or tips on how to approach making an app mobile responsive. I tried to make it responsive but it isn't working as expected. I'm aware, you must be busy , but I would greatly appreciate it if you could please help me in any possible capacity to make the app responsive.

Just to be clear, login and signup page works perfectly fine on mobile as well however, actual problem arises when logged in and clicking on specific user to initiate the chat. I'm attaching the screenshots of the app when opened on mobile.

Once again, thank you so much for your invaluable contribution to the community through your tutorial. I truly appreciate your time and expertise.

Looking forward to your response.

Warm regards,

Amol

Screenshot 2024-04-05 121346
Screenshot 2024-04-05 121651

mongodb issue showing

Annotation 2024-06-13 073316
Error connecting to MongoDB The uri parameter to openUri() must be a string, got "undefined". Make sure the first parameter to mongoose.connect() or mongoose.createConnection() is a string. when i conncet it showing i have add mongodb url

Logic error in `useListenMessages` hook

First of all thank you for this app, I followed through and learned a lot about developing chat app.

There's an issue I'd like to point out though, which resides in the useListenMessages hook. The current implementation updates messages whenever a new message comes in without checking the sender, meaning if I'm opening the conversation with A, then new messages from B will also update the chat window. The solution is to simply check if the sender matches the current conversation, and then update current messages accordingly.

Then again, it was a good run with your YT tutorial, thanks again.

Message time

When sending a message, the message time appears as "NAN." However, upon selecting another user and then returning to the user to whom the message was sent, the correct time is displayed.

When sending a message

Screenshot 2024-04-01 at 5 42 25โ€ฏPM

returning to the user to whom the message was sent

Screenshot 2024-04-01 at 5 42 33โ€ฏPM

In real time chatting

in real time chat we set our message context with updated message and set it . but actually its not tru because if reciver selected conversation is diffrent then also he find your mesdsage but it should not let's take and example
if there is thee user jhon , bob and alice now jhon and bob doing chat (online) in this code if jhon send message to bob and if selected conversation of bob is alice then also it shows new upcoming message but bob and alice neve do chat new upcoming message is actully of jhon if we refresh it then it comes propely due to context refresh in this case .

to solve this :
we have to check if selected conversation id is same as reciver id then and then update message context otherwise dont update context of message.

`const useListenMessages = () => {
const { socket } = useSocketContext();
const { messages, setMessages, selectedConversation } = useConversation();
const { user } = useAutherContext();

useEffect(() => {
socket?.on("new-message", ( newMessage ) => {
const check = newMessage.receiverId == selectedConversation.id
console.log(selectedConversation);
newMessage.shake = true;
const sound = new Audio(notificationSound);
sound.play();

  if (check) {
    setMessages([...messages, newMessage]);
  }
});

return () => {
  socket?.off("new-message");
};

}, [socket, messages, setMessages]);
};

export default useListenMessages;`

Appreciation for Your JS ChatApp and Help with Embedding

I hope this message finds you well. I wanted to express my heartfelt appreciation for your JavaScript chatApp. It has been an invaluable tool for my website, and I am deeply grateful for your hard work and dedication in creating such a useful application.

I am currently in the process of embedding the chat app into my webpage using an <iframe>, but I have encountered some difficulties and errors along the way. I have attached a screenshot of the error message I am receiving for your reference. Could you please provide me with the necessary steps or guidance to successfully embed the chat app on my webpage.
Thank you once again for your amazing work, and I truly appreciate your assistance in helping me resolve this issue

Screenshot_20240302_082113

Online Users not getting displayed

Hello Everyone
I'm getting an empty array when trying to get online users .
My code is as follows :

// SocketContext.jsx : 
import { createContext, useState, useEffect, useContext } from "react";
import { useAuthContext } from "./AuthContext";
import io from "socket.io-client";

const SocketContext = createContext();

export const useSocketContext = () => {
  return useContext(SocketContext);
};

export const SocketContextProvider = ({ children }) => {
  const [socket, setSocket] = useState(null);
  const [onlineUsers, setOnlineUsers] = useState([]);
  const { authUser } = useAuthContext();

  useEffect(() => {
    if (authUser) {
      const socket = io("http://localhost:3000", {
        query: {
          userId: authUser._id,
        },
      });

      setSocket(socket);

      // socket.on() is used to listen to the events. can be used both on client and server side
      socket.on("getOnlineUsers", (users) => {
        setOnlineUsers(users);
      });

      return () => socket.close();
    } else {
      if (socket) {
        socket.close();
        setSocket(null);
      }
    }
  }, [authUser]);

  return (
    <SocketContext.Provider value={{ socket, onlineUsers }}>
      {children}
    </SocketContext.Provider>
  );
};
// conversation.jsx :
import { useSocketContext } from "../../context/SocketContext";
import useConversation from "../../zustand/useConversation";
function Conversation({ conversation, lastIdx, emoji }) {
  const { selectedConversation, setSelectedConversation } = useConversation();
  const isSelected = selectedConversation?._id === conversation._id;
  const { onlineUsers } = useSocketContext();
  console.log(onlineUsers);
  const isOnline = onlineUsers.includes(conversation._id);
  return (
    <>
      <div
        className={`flex gap-2 items-center hover:bg-purple-900 rounded p-2 py-1 cursor-pointer
          ${isSelected ? "bg-purple-900" : ""}`}
        onClick={() => setSelectedConversation(conversation)}
      >
        <div className={`avatar ${isOnline ? "online" : "offline"}`}>
          <div className="w-12 rounded-full">
            <img src={conversation.profilePicture} alt="user avatar" />
          </div>
        </div>
        <div className="flex flex-col flex-1">
          <div className="flex gap-3 justify-between">
            <p className="font-bold text-gray-200">{conversation.fullName}</p>
            <span className="text-xl">{emoji}</span>
          </div>
        </div>
      </div>
      {!lastIdx && <div className="divider my-0 py-0 h-1" />}
    </>
  );
}

export default Conversation;
 

I am getting an empty array as online users :
Array(0)
[]

Below is my server side code :

// socket.js
import { Server } from "socket.io";
import http from "http";
import express from "express";

const app = express();

const server = http.createServer(app);
const io = new Server(server, {
  cors: {
    origin: ["http://localhost:3000"],
    methods: ["GET", "POST"],
  },
});

export const getReceiverSocketId = (receiverId) => {
  return userSocketMap[receiverId];
};

const userSocketMap = {}; // {userId: socketId}

io.on("connection", (socket) => {
  console.log("a user connected", socket.id);

  const userId = socket.handshake.query.userId;
  if (userId != "undefined") userSocketMap[userId] = socket.id;

  // io.emit() is used to send events to all the connected clients
  io.emit("getOnlineUsers", Object.keys(userSocketMap));

  // socket.on() is used to listen to the events. can be used both on client and server side
  socket.on("disconnect", () => {
    console.log("user disconnected", socket.id);
    delete userSocketMap[userId];
    io.emit("getOnlineUsers", Object.keys(userSocketMap));
  });
});

export { app, io, server };

I tried reading socket.js documetation but i'm not able to find the error
Any help is appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.