[React + Node.js]: Implement Web Socket with Socket.io
React
Node.js
03/20/2020
Websocket
Typical approach of Node.js application requires client to request data, and the server sends the response back--this is HTTP protocol, but what if you want to notify a client when there's a change on the server? Imagine a messenger application. Your friend needs to be able to receive your message in real-time without having to request something to the server. This is where websocket comes into play. Built over HTTP, websockets enable two-way communication where the server can push data to the client without receiving request. Socket.io is a popular library that you can use to establish websocket.
Overview
As an example, I'll be using this MERN stack app to implement websocket. As user adds/deletes an entry, the updated data will be updated in real-time on other browsers as well. The complete project is available here.
Socket.io on the server
Install socket.io on the server side
npm i socket.ioCreate a utility to initialize & get io
socket.js
let iomodule.exports = {  init: httpServer => {    io = require("socket.io")(httpServer)    return io  },  getIO: () => {    if (!io) {      throw new Error("Socket.io is not initialized")    }    return io  },}Creating socket io connection
app.js
// ...// DB connectionmongoose  .connect(MONGODB_URI)  .then(result => {    const port = process.env.PORT || 8080    const server = app.listen(port, () => {      console.log(`Listening on port ${port}...`)    })
    // Create socket io connection    const io = require("./util/socket").init(server)    io.on("connection", socket => {      console.log("Client connected")    })  })  .catch(err => {    // Handle error  })Check the import directory of socket util
Sending message to client on adding user
controllers/user.js
const User = require("../models/user")const io = require("../socket") 
// ...
exports.postUser = async (req, res, next) => {  try {    let occupation = req.body.occupation    if (!occupation) occupation = "unemployed"    const user = new User({      name: req.body.name,      age: req.body.age,      occupation: occupation,    })    await user.save()
    // Sends message to all connected users    io.getIO().emit("user event", {      action: "add",      user: { ...user._doc },    })
    res.status(201).json({      message: "User created",      user: user,    })  } catch (err) {    if (!err.statusCode) {      err.statusCode = 500    }    next(err)  }}Sending message to client on deleting user
controllers/user.js
exports.deleteUser = async (req, res, next) => {  const userId = req.params.userId  try {    const user = await User.findById(userId)    if (!user) {      const error = new Error("Couldn't find the user")      error.statusCode = 404      throw error    }    await User.findByIdAndRemove(userId)
    // Sends message to all connected users    io.getIO().emit("user event", {      action: "delete",      userId: userId,    })
    res.status(200).json({ message: "User removed" })  } catch (err) {    if (!err.statusCode) {      err.statusCode = 500    }    next(err)  }}Client side
Install socket.io-client on the client side
npm i socket.io-clientCreate socket connection & Update state with received data
front-end/App.js
import React, { useState, useEffect } from "react";import openSocket from "socket.io-client"; import User from "./user";import UserAddForm from "./user-add-form";import "./App.css";
const App = () => {  const [addLoading, setAddLoading] = useState(false);  const [deleteLoading, setDeleteLoading] = useState(false);  const [users, setUsers] = useState([]);
  useEffect(() => {    fetchUsers();    createSocketConnection();   }, []);
  const createSocketConnection = () => {    const socket = openSocket(process.env.REACT_APP_FETCH_URL);    socket.on("user event", data => {      if (data.action === "add") {        setUsers(prevUsers => [data.user, ...prevUsers]);      } else if (data.action === "delete") {        setUsers(prevUsers =>          prevUsers.filter(user => user._id !== data.userId)        );      }    });  };
  const fetchUsers = async () => { ... };  const handleAdd = async formData => { ... };  const handleDelete = async userId => { ... };  return ( ... );};
user eventlistens to the event that was sent from the server