在這篇部落格中,我們將使用 Socket.io 來構建一個 即時聊天應用程式,進行雙向通信,使用 Express.js 作為伺服器,React.js 作為前端,並使用 Chakra UI 進行樣式設計。我們將使用 Vite 快速開發來設置專案。

主要特點:

  • 基於使用者ID的聊天: 生成隨機的 userId 並儲存在會話儲存中。
  • 訊息顯示: 我們的訊息顯示在左側,其他人的顯示在右側,每個訊息都有一個圖示。

以下是此專案的示範:

Socket demo

chat demo

Server socket logs

讓我們開始吧!

1. 設置專案

創建一個名為 chat-app 的包裝資料夾,其中包含我們的前端和後端:

mkdir chat-app
cd chat-app

後端設置: 使用 Express.js 和 Socket.io
首先,為後端創建一個資料夾並使用 npm init -y 初始化:

mkdir chat-backend
cd chat-backend
npm init -y

現在安裝必要的套件:

npm install express socket.io

為後端創建以下文件結構:

chat-backend/
│
├── server.js
└── package.json

server.js - Express 和 Socket.io
以下是如何設置 Express 伺服器以及 Socket.io

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:5173',
    methods: ['GET', 'POST']
  }
});

io.on('connection', (socket) => {
  console.log('一位使用者已連接:', socket.id);

  socket.on('sendMessage', (message) => {
    io.emit('receiveMessage', message);
  });

  socket.on('disconnect', () => {
    console.log('一位使用者已斷開連接');
  });
});

server.listen(4000, () => {
  console.log('伺服器正在監聽端口 4000');
});

這段程式碼創建了一個在端口 4000 上監聽的 Express 伺服器,並設置 Socket.io 來處理 即時通訊。當使用者發送訊息(sendMessage 事件)時,會將其廣播給所有已連接的客戶端。

前端設置:使用 Vite 與 React 和 Chakra UI

創建一個 Vite React 專案,並按照以下截圖進行操作(在 chat-app 中創建專案,而不是在 chat-backend 中):

npm create vite@latest

Creating project

Selecting Reactjs

Selecting Js

進入專案資料夾並安裝必要的依賴:

cd chat-frontend
npm install socket.io-client @chakra-ui/react @emotion/react @emotion/styled framer-motion

現在,讓我們為聊天應用程式創建一個基本結構。

2. 實現聊天前端

前端的結構將如下所示:

chat-frontend/
│
├── src/
│   ├── components/
│   │   └── ChatBox.jsx
│   ├── App.jsx
│   └── main.jsx
├── index.html
└── package.json

App.jsx

App.jsx 中,設置 Chakra UI 並渲染 ChatBox 組件:

import { ChakraProvider, Box, Heading } from "@chakra-ui/react";
import ChatBox from "./components/ChatBox";

function App() {
  return (
    <ChakraProvider>
      <Box p={5}>
        <Heading as="h1" mb={6}>
          即時聊天
        </Heading>
        <ChatBox />
      </Box>
    </ChakraProvider>
  );
}

export default App;

ChatBox.jsx

這裡是主要聊天邏輯的部分。我們將使用 Socket.io 來監聽訊息並處理即時更新。隨機生成一個 userId 並儲存在會話儲存中,聊天界面將使用 Chakra UI 構建。

import React, { useState, useEffect } from "react";
import { Box, Input, Button, HStack, VStack, Text, Avatar } from "@chakra-ui/react";
import { io } from "socket.io-client";

const socket = io("http://localhost:4000");

const ChatBox = () => {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState("");
  const [userId, setUserId] = useState(null);

  useEffect(() => {
    // 生成或從會話儲存中獲取 userId
    let storedUserId = sessionStorage.getItem("userId");
    if (!storedUserId) {
      storedUserId = Math.random().toString(36).substring(7);
      sessionStorage.setItem("userId", storedUserId);
    }
    setUserId(storedUserId);

    // 監聽訊息
    socket.on("receiveMessage", (message) => {
      setMessages((prevMessages) => [...prevMessages, message]);
    });

    return () => {
      socket.off("receiveMessage");
    };
  }, []);

  const sendMessage = () => {
    if (input.trim()) {
      const message = {
        userId,
        text: input,
      };
      socket.emit("sendMessage", message);
      setInput("");
    }
  };

  return (
    <VStack spacing={4} align="stretch">
      <Box h="400px" p={4} borderWidth={1} borderRadius="lg" overflowY="auto">
        {messages.map((msg, index) => (
          <HStack key={index} justify={msg.userId === userId ? "flex-start" : "flex-end"}>
            {msg.userId === userId && <Avatar name="我" />}
            <Box
              bg={msg.userId === userId ? "blue.100" : "green.100"}
              p={3}
              borderRadius="lg"
              maxW="70%"
            >
              <Text>{msg.text}</Text>
            </Box>
            {msg.userId !== userId && <Avatar name="其他" />}
          </HStack>
        ))}
      </Box>

      <HStack>
        <Input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="輸入訊息"
        />
        <Button onClick={sendMessage} colorScheme="teal">
          發送
        </Button>
      </HStack>
    </VStack>
  );
};

export default ChatBox;

運作方式:

  • 隨機 userId: 我們生成一個隨機字串作為 userId,並將其儲存在 sessionStorage 中。這確保即使重新載入頁面,您也會在會話中保留相同的 userId。

  • Socket.io 用於訊息傳遞: 應用程式會監聽伺服器的 receiveMessage 事件並顯示進來的訊息。當使用者發送訊息時,它是透過 Socket.io 發送的,UI 即時更新。

  • Chakra UI 樣式: 訊息顯示在一個框中,我們的訊息對齊到左側(藍色背景),而其他人的訊息對齊到右側(綠色背景)。每則訊息也有一個頭像,提供簡單的個性化聊天介面。

3. 運行應用程式

啟動後端:

cd chat-backend
node server.js

啟動前端:

cd chat-frontend
npm run dev

現在,在多個瀏覽器窗口中打開 http://localhost:5173 來測試即時聊天功能。您將看到每位使用者的訊息顯示其獨特的 userId

您已成功構建了一個使用 Socket.ioExpressReact.jsChakra UI 的即時聊天應用程式,並使用 Vite 設置專案! 🎉

這個應用程式展示了 Socket.io 在即時通信中的力量 💬 和 Chakra UI 提供的乾淨響應界面 📱。

您可以透過添加功能如 聊天房間 🏠、訊息持久化 💾 和 使用者身份驗證 🔒 擴展此專案。

這篇部落格到此為止!請保持關注更多更新,並繼續構建驚人的應用程式! 💻✨
快樂編碼! 😊


原文出處:https://dev.to/jagroop2001/building-a-real-time-chat-application-with-socketio-express-reactjs-and-chakra-ui-vite-setup-5h5p


共有 0 則留言