Logo

dev-resources.site

for different kinds of informations.

πŸ’¬ Building a Real-time Chat Feature for Virtual Gift Store Using Socket.IO with MERN Stack πŸš€

Published at
9/29/2024
Categories
react
node
mongoose
socketio
Author
sajjad54
Categories
4 categories in total
react
open
node
open
mongoose
open
socketio
open
Author
8 person written this
sajjad54
open
πŸ’¬ Building a Real-time Chat Feature for Virtual Gift Store Using Socket.IO with MERN Stack πŸš€

Chat feature in virtual gift store

Project Overview:

Giftly is a virtual gift store management platform where users can communicate with the admin in real-time using a built-in chat feature. This feature enables seamless interaction between normal users and the admin, making the customer support process faster and more interactive. The chat functionality is built using Node.js, React.js, Mongoose, Socket.IO, and Express.js.

Key Features of the Chat System

  1. - Real-time Messaging: Communication happens instantly between users and the admin using Socket.IO.
  2. - User Roles:
  3. - Admin: Can view and respond to all users.
  4. - Normal users: Can only chat with the admin.
  5. - Persistent Chat History: Chat messages are stored in MongoDB and retrieved upon reconnecting.
  6. - Notifications: Real-time toast notifications for new messages.

Technologies Used

  • Backend: Node.js, Express.js, Mongoose (MongoDB)
  • Frontend: React.js, CSS
  • WebSocket: Socket.IO for real-time communication
  • Database: MongoDB (Atlas)

System Architecture

Frontend (React.js)

Main components for this feature include:

  1. ChatContainer: Manages the chat interface, handling authentication and message rendering.
  2. ChatList: Displays messages based on whether the user is the sender or receiver.
  3. Socket.IO Client: Initializes the connection and handles real-time updates.
  4. Backend (Node.js, Express.js)
  5. Routes: Handles HTTP requests and interacts with the MongoDB database.
  6. Socket.IO Server: Manages chat rooms and message broadcasting.
  7. Mongoose Models: Defines the schema for storing chat data.

Benefits of Using Socket.IO

  1. Real-Time Communication: Socket.IO allows instant message delivery without delays, creating a seamless chat experience.
  2. Cross-Browser Support: It provides real-time connections that work across different browsers and platforms.
  3. Automatic Reconnection: In case of network disruptions, Socket.IO automatically reconnects the user without losing the chat session.
  4. Broadcasting to Rooms: Messages are broadcasted only to users in specific chat rooms, optimizing the flow of communication.

Backend Code - Mongoose Schema Definition

This schema captures sender and receiver details, message content, profile images, and timestamps.

const mongoose = require('mongoose');

const chatSchema = new mongoose.Schema({
    senderUsername: String,
    receiverUsername: String,
    message: String,
    profileImage: String,
    timestamp: { type: Date, default: Date.now }
});

const Chat = mongoose.model('chat-message', chatSchema);
module.exports = Chat;
Enter fullscreen mode Exit fullscreen mode

Backend Setup (Express.js & Socket.IO)

The backend is configured to handle real-time message exchanges and store chat data in MongoDB.

const express = require("express");
const cors = require("cors");
require("dotenv").config();
const mongoose = require("mongoose");
const http = require("http");
const { Server } = require("socket.io");
const Chat = require("./model/chatModel");

const app = express();
const server = http.createServer(app);

// Middleware
app.use(cors({ origin: process.env.CLIENT_URL, credentials: true }));
app.use(express.json());

// Connect to MongoDB
mongoose.connect(process.env.MONGO_URI, { dbName: 'Giftly-server-db' })
    .then(() => console.log("Giftly DB connected"))
    .catch((err) => console.log(err));

// Socket.IO Setup
const io = new Server(server, { cors: { origin: process.env.CLIENT_URL } });

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

    socket.on('joinRoom', ({ sender, receiver }) => {
        const room = [sender, receiver].sort().join('-');
        socket.join(room);
        loadMessages(socket, sender, receiver);  // Load previous chats
    });

    socket.on('newMessage', async (msg) => {
        const newMessage = new Chat(msg);
        await newMessage.save();
        io.to([msg.senderUsername, msg.receiverUsername].sort().join('-')).emit('message', msg);
    });

    socket.on("disconnect", () => {
        console.log("User disconnected");
    });
});

server.listen(process.env.PORT, () => {
    console.log(`Giftly server is running on port ${process.env.PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

Frontend (React.js) - ChatContainer Component

The ChatContainer component renders the chat interface and manages sending/receiving messages via Socket.IO.

import React, { useContext, useEffect, useState } from "react";
import socketIOClient from "socket.io-client";
import ChatLists from './ChatList';
import './style.css';
import toast from "react-hot-toast";
import { AuthContext } from "../../Provider/AuthProvider";

const socket = socketIOClient(process.env.REACT_APP_SERVER_URL, { autoConnect: false });

const ChatContainer = () => {
    const { user } = useContext(AuthContext);
    const [text, setText] = useState('');
    const [userInfo, setUserInfo] = useState(() => JSON.parse(localStorage.getItem("userInfo")));
    const [receiver, setReceiver] = useState(() => localStorage.getItem("receiver"));
    const [chats, setChats] = useState([]);

    // Fetch previous chats
    const fetchPreviousChats = async (sender, receiver) => {
        const response = await fetch(`${process.env.REACT_APP_SERVER_URL}/chat/getChats?sender=${sender}&receiver=${receiver}`);
        const previousChats = await response.json();
        setChats(previousChats);
    };

    // Initialize Socket
    useEffect(() => {
        socket.connect();
        if (userInfo && receiver) {
            socket.emit("joinRoom", { sender: userInfo.userName, receiver });
        }
        socket.on("message", (msg) => setChats(prev => [...prev, msg]));
        return () => socket.disconnect();
    }, [userInfo, receiver]);

    const handleSend = () => {
        if (text.trim()) {
            const newChat = { senderUsername: userInfo.userName, receiverUsername: receiver, message: text };
            socket.emit("newMessage", newChat);
            setText('');
        }
    };

    return (
        <div className="chat-container">
            <div className="chat-header">Chat with {receiver}</div>
            <ChatLists chats={chats} />
            <div className="chat-input">
                <input type="text" value={text} onChange={(e) => setText(e.target.value)} />
                <button onClick={handleSend}>Send</button>
            </div>
        </div>
    );
};

export default ChatContainer;
Enter fullscreen mode Exit fullscreen mode

Notification Handling in Frontend

Using react-hot-toast for real-time notifications when a new message arrives.

socket.on("notification", (notification) => {
    if (notification.receiver === userInfo.userName) {
        toast.success(notification.message, { duration: 6000, position: 'top-center' });
    }
});
Enter fullscreen mode Exit fullscreen mode

Socket.IO Methods Explained

  1. io.on('connection'): Establishes a WebSocket connection when a user connects.
  2. socket.emit('joinRoom'): Joins a chat room created between the sender and receiver.
  3. socket.on('newMessage'): Receives a new message from the client and stores it in the database.
  4. io.to(room).emit('message'): Broadcasts the message to users in a specific chat room.
  5. socket.on('disconnect'): Handles user disconnection and cleanup.

Future Enhancements

  1. File Sharing: Allow users to send images and files.
  2. Typing Indicators: Display real-time typing status for a better interaction experience.
  3. Push Notifications: Integrate push notifications to alert users when offline.

Setup Instructions

Backend Setup

Clone the repository:

git clone https://github.com/your-repo-url/giftly-chat-app.git
cd giftly-chat-app/server
npm install

Enter fullscreen mode Exit fullscreen mode

Create a .env file in the server directory:

MONGO_URI=mongodb+srv://<username>:<password>@cluster0.mongodb.net/giftly-server-db
PORT=<your-server-port>
CLIENT_URL=http://localhost:5173

Enter fullscreen mode Exit fullscreen mode

*Run the backend server:
*

npm run start
Enter fullscreen mode Exit fullscreen mode

Frontend Setup (React.js)

Navigate to the client folder:

cd ../client
npm install
npm run dev
Enter fullscreen mode Exit fullscreen mode

Create a .env file in the client folder:

REACT_APP_SERVER_URL=http://localhost:<your-server-port>
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

The Giftly chat feature is a scalable real-time chat solution, enabling instant communication between users and admins. Socket.IO simplifies the WebSocket management, ensuring smooth and efficient message exchanges with real-time notifications. Future enhancements will bring more interaction to users, including file sharing, typing indicators, and offline notifications.

Happy coding! πŸš€

mongoose Article's
30 articles in total
Favicon
Crudify: Automate Your Mongoose CRUD Operations in NestJS
Favicon
6 Steps to Set Up MongoDB Atlas for Node.js Applications
Favicon
Mysql 101 for Mongoose developer.
Favicon
Tutorial de Instalação: Express com MongoDB e Mongoose
Favicon
Today’s new knowledge #6(Mongoose)
Favicon
Today’s new knowledge #10 (Building a Flexible Query Builder for MongoDB with Mongoose)
Favicon
mongoose connect to express
Favicon
I Fumbled on a Next.js MongoDB Error and Learned the Key Differences Between Mongoose and MongoClient
Favicon
Setup Eslint Prettier in a TypeScript project with mongoose ODM
Favicon
Bootcamping 01: An Unexpected Behavior of Mongoose
Favicon
Common Myths About Mongoose
Favicon
5 Quick And Easy MongoDB Optimizations (part 1)
Favicon
Mongoose Interview Questions
Favicon
MongoDB vs. Mongoose: Understanding Their Roles and Differences
Favicon
We finally have a fullstack framework for MongoDB
Favicon
Mongoose
Favicon
πŸ’¬ Building a Real-time Chat Feature for Virtual Gift Store Using Socket.IO with MERN Stack πŸš€
Favicon
The Power of exec() in Mongoose: Unlocking Better Query Execution
Favicon
Enhancing Mongoose Reference Handling in Node.js
Favicon
Mongoose Documentation
Favicon
How to Connect MongoDB with Node.js: A Comprehensive Guide
Favicon
Updating Non-Primitive Data in an Array Using Transactions and Rollbacks
Favicon
Method Chaining in Mongoose: A Brief Overview
Favicon
Understanding Transactions and Rollbacks in MongoDB
Favicon
Understanding Populating Referencing Fields in Mongoose
Favicon
How to Use Bcrypt for Password Hashing in Node.js
Favicon
Getting Started with Mongoose
Favicon
Running Unit Tests with MongoDB in a Node.js Express Application using Jest
Favicon
Setting up MongoDB using Mongoose in Node.js
Favicon
I built an open-source schema visualisation tool for mongoose

Featured ones: