Back to articles

Building a Real-Time Chat Application with React and Socket.IO

AuthorMajd Muhtaseb05/09/202510 minutes
Building a Real-Time Chat Application with React and Socket.IO

Introduction

This article guides you through creating a basic real-time chat application. We'll leverage React for the user interface and Socket.IO for handling real-time bidirectional communication between the client and server.

Prerequisites

  • Node.js and npm installed
  • Basic understanding of React

Setting up the Server (Node.js with Socket.IO)

First, create a server-side application using Node.js and install the necessary dependencies:

mkdir chat-server
cd chat-server
npm init -y
npm install socket.io express

Create a file named server.js and add the following code:

const express = require('express');
const http = require('http');
const { Server } = require("socket.io");

const app = express();
const server = http.createServer(app);
const io = new Server(server, {
  cors: {
    origin: "http://localhost:3000", // Replace with your React app's URL
    methods: ["GET", "POST"]
  }
});

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

  socket.on('chat message', (msg) => {
    io.emit('chat message', { message: msg, id: socket.id });
  });

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

const port = 4000; // Example port
server.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

Run the server:

node server.js

Building the React Client

Create a new React application:

npx create-react-app chat-client
cd chat-client
npm install socket.io-client

Replace the contents of src/App.js with the following:

import React, { useState, useEffect, useRef } from 'react';
import io from 'socket.io-client';
import './App.css';

const socket = io('http://localhost:4000'); // Replace with your server URL

function App() {
  const [messages, setMessages] = useState([]);
  const [newMessage, setNewMessage] = useState('');
  const messagesEndRef = useRef(null);


  useEffect(() => {
    socket.on('chat message', (msg) => {
      setMessages(prevMessages => [...prevMessages, msg]);
    });

    return () => {
      socket.off('chat message');
    };
  }, []);

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" })
  }, [messages]);

  const sendMessage = (e) => {
    e.preventDefault();
    if (newMessage) {
      socket.emit('chat message', newMessage);
      setNewMessage('');
    }
  };

  return (
    <div className="App">
      <h1>Real-time Chat</h1>
      <div className="messages">
        {messages.map((msg, index) => (
          <div key={index}>
            <strong>User {msg.id}:</strong> {msg.message}
          </div>
        ))}
        <div ref={messagesEndRef} />
      </div>
      <form onSubmit={sendMessage}>
        <input
          type="text"
          value={newMessage}
          onChange={(e) => setNewMessage(e.target.value)}
          placeholder="Type your message..."
        />
        <button type="submit">Send</button>
      </form>
    </div>
  );
}

export default App;

Add some basic styling to src/App.css:

.App {
  text-align: center;
}

.messages {
  height: 300px;
  overflow-y: scroll;
  border: 1px solid #ccc;
  margin-bottom: 10px;
  padding: 10px;
}

Start the React application:

npm start

Conclusion

You have now built a simple real-time chat application using React and Socket.IO. This example can be expanded upon to include features such as user authentication, private messaging, and more complex UI elements.