...

Connecting React and Node.js with Socket.IO for Real-Time Communication

This guide walks you through creating a real-time web application using React (with TailwindCSS for styling) and Node.js (with Express and Socket.IO for the backend). You’ll learn how to serve a React app from Express, establish a Socket.IO connection, send and receive messages in real time, and use a proxy during development for seamless integration.

Real-time communication is a game changer for modern web applications. Whether you’re building a chat app, live dashboard, multiplayer game, or collaborative tool, Socket.IO provides a simple way to connect the frontend and backend instantly.

In this tutorial, we’ll build a small app where a Node.js + Express server sends a message to a React frontend after the client connects. We’ll also use TailwindCSS for styling and Vite's development proxy for smooth local development.

Project Structure


my-app/
  ├── client/   # React frontend
  ├── server.js # Node.js backend
Step 1 – Backend Setup (Node.js + Express + Socket.IO)

mkdir backend && cd backend
npm init -y


2. Install Dependencies

npm install express --save
npm install socket.io
npm i --save path
npm i nodemon -D



Step 2 – Frontend Setup (React + Vite + TailwindCSS)

Create React App with Vite

npm create vite@latest client



Go to Client Folder

cd client


3. Install Socket.IO Client


npm install socket.io-client



4. Install TailwindCSS (Optional)

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init



Tailwind Config (tailwind.config.js)


module.exports = {
  content: ["./index.html", "./src/**/*.{js,jsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};



Import Tailwind in index.css
@tailwind base;
@tailwind components;
@tailwind utilities;



Step 3 – Backend Code (server.js)


const express = require("express");
const app = express();
const http = require("http");
const expressserver = http.createServer(app);
const port = 5000;
const { Server } = require("socket.io");
const io = new Server(expressserver);
const path = require("path");

// Serve React build files
app.use(express.static(path.join(__dirname, "client", "dist")));
app.use(express.static(path.join(__dirname, "client", "dist", "assets")));

// Handle all routes
app.get("/{*any}", (req, res) => {
    res.sendFile(path.resolve(__dirname, "client", "dist", "index.html"));
});

// Socket.IO connection
io.on("connection", (socket) => {
    console.log("A user connected:", socket.id);

    setTimeout(() => {
        socket.emit("msg", "This is message from express server");
    }, 2000);

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

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




Step 4 – Frontend Code (App.jsx)


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

export class App extends Component {
    constructor() {
        super();
        this.state = { message: "" };
    }

    componentDidMount() {
        const socket = io.connect("/");
        socket.on("msg", (data) => {
            this.setState({ message: data });
        });
    }

    render() {
        return (
            <div className="h-screen flex flex-col items-center justify-center bg-gradient-to-br from-blue-50 via-white to-blue-100">
                <div className="p-8 bg-white rounded-2xl shadow-lg text-center max-w-md">
                    <h1 className="text-2xl font-extrabold text-blue-700 drop-shadow-sm">
                        🚀 Welcome to React + Socket.IO
                    </h1>
                    <p className="mt-4 text-lg text-gray-600">
                        Real-time magic is happening right here.
                    </p>
                    <p className="mt-2 text-gray-500 italic">
                        Connected to the server and ready to receive updates!
                    </p>
                    {this.state.message && (
                        <div className="mt-6 px-4 py-2 bg-green-100 text-green-700 rounded-lg shadow-sm">
                            <strong>Server says:</strong> {this.state.message}
                        </div>
                    )}
                </div>
            </div>
        );
    }
}

export default App;




Step 5 – Development Proxy

In client/package.json add:


"proxy": "http://localhost:5000"





This forwards /socket.io requests to the backend during development, avoiding CORS issues. Without this, you’d need:


io.connect("http://localhost:5000");


Step 6 – Running the App
Backend
npx nodemon server.js

Frontend
npm run dev or build



How React and Node Connect Here

Node.js + Express serves static React files and handles WebSocket connections via Socket.IO.

React connects to the backend using Socket.IO client.

Vite proxy simplifies local development.

TailwindCSS styles the interface.

Conclusion

By combining React, Node.js, Express, and Socket.IO, you can create powerful real-time applications. This same approach can power chat apps, live notifications, multiplayer games, or collaborative tools — all with instant updates.

William Anderson

I am a versatile Full-Stack Web Developer with a strong focus on Laravel, Livewire, Vue.js, and Tailwind CSS. With extensive experience in backend development, I specialize in building scalable, efficient, and high-performance web applications.