Комунікація в реальному часі з Socket.IO: інтеграція React.js та Node.js

pic

Socket.IO — це потужна бібліотека, яка забезпечує реальний час, двосторонню та подієву комунікацію між клієнтом (наприклад, веб-браузером або мобільним додатком) та сервером. Вона широко використовується в веб-додатках для реалізації таких функцій, як живий чат, реальні сповіщення, ігри та інструменти для співпраці.

Сьогодні ми розглянемо комунікацію в реальному часі з Socket.IO, використовуючи React Js та Node Js. Почнемо з налаштування сервера Socket.IO (бекенд), а потім перейдемо до створення додатку на React (фронтенд).

Сервер Socket.IO

server/  
│  
├── index.js # Точка входу на сервер  
├── package.json # Метадані проекту та залежності

Вам потрібно встановити наступні пакети у вашому бекенд-коді: express, cors, nodemon (опційно) та socket.io

npm init -y  
npm install express cors nodemon socket.io

CORS є важливим при роботі з Socket.IO в повноцінному стеку, оскільки ваш бекенд-сервер буде надавати дані вашому фронтенду. Для того, щоб фронтенд зміг встановити з'єднання з бекендом, потрібно налаштувати CORS; інакше React заблокує з'єднання через обмеження на перехресні запити.

Використовуйте наступний код для вашого файлу index.js у бекенд-коді. Він налаштовує сервер та гарантує, що він буде успішно запущений.

import express from 'express';  
import http from 'http';  
import cors from 'cors';  
import { Server } from 'socket.io';  

const app = express();  
const PORT = process.env.PORT || 4000 // За замовчуванням порт 4000, якщо не встановлено в змінних середовища  

// Мідлвар  
app.use(cors())  
app.use(express.json())  

const server = http.createServer(app)  

const io = new Server(server, {  
 cors: {  
 origin: 'http://localhost:3000', // Дозволити запити з React додатку (URL фронтенду)  
 methods: ['GET', 'POST'], // Дозволені HTTP методи  
 },  
})  

// Обробка WebSocket з'єднань  
io.on('connection', (socket) => {  
 console.log(`User connected: ${socket.id}`)  

 socket.on('join_room', (data) => {  
 socket.join(data.room)  
 })  

 socket.on('send_message', (data) => {  
 const { message, room, userName, timeStamp } = data  
 socket  
 .to(data.room)  
 .emit('receive_message', {  
 message,  
 room,  
 userName,  
 timeStamp,  
 type: 'receive',  
 })  
 })  
})  

// Запуск сервера  
const startServer = async () => {  
 try {  
 server.listen(PORT, () => {  
 console.log(`Server running on port http://localhost:${PORT}`)  
 })  
 } catch (error) {  
 process.exit(1)  
 }  
}  

startServer()

React-додаток

npx create-react-app client  
Потрібно встановити наступні пакети:  
[email protected]  
OK, продовжити? (y) y  

// Змініть директорію і перейдіть до папки клієнта  
cd client  

// Тепер встановіть клієнтський пакет для Socket.IO  
npm install socket.io-client

Ваша директорія client повинна виглядати так після виконання вищеописаних кроків:

client/  
│  
├── node_modules/  
├── public/  
├──src/  
 ├── App.js  
 ├── App.css  
 ├── index.js  
├── package.json

Ви можете видалити інші файли, оскільки для налаштування базового проекту з Socket.IO необхідні лише ці файли.

Використовуйте наступний код для вашого файлу App.js в коді клієнта. Це налаштує базову структуру для чату. У цій реалізації користувачам потрібно буде ввести номер кімнати та своє ім’я користувача.
Як тільки вони потрапляють у кімнату, вони можуть обмінюватися повідомленнями з іншими учасниками тієї ж групи.

import { useEffect, useState } from 'react'  
import io from 'socket.io-client'  

const socket = io('http://localhost:4000') // URL бекенд-сервера  

const initalFormData = {  
 room: '',  
 userName: '',  
 message: '',  
}  

function App() {  
 const [formData, setFormData] = useState(initalFormData)  

 const [messages, setMessages] = useState([])  

 const handleChange = (e) => {  
 const { name, value } = e.target  
 setFormData({ ...formData, [name]: value })  
 }  

 const handleEnterRoom = () => {  
 socket.emit('join_room', {  
 room: formData.room,  
 })  
 }  

 const handleSendMessage = () => {  
 const messageData = {  
 message: formData.message,  
 room: formData.room,  
 userName: formData.userName,  
 timeStamp: new Date().toISOString(),  
 type: 'sent',  
 }  
 socket.emit('send_message', messageData)  

 setMessages((prevMessages) => [...prevMessages, messageData])  

 // Очищення поля введення повідомлення  
 setFormData((prev) => ({ ...prev, message: '' }))  
 }  

 useEffect(() => {  
 socket.on('receive_message', (data) => {  
 setMessages((prevMessages) => [  
 ...prevMessages,  
 { ...data, type: 'received' }, // Позначаємо це повідомлення як отримане  
 ])  
 })  

 return () => {  
 socket.off('receive_message') // Очищення прослуховувача при демонтажі компонента  
 }  
 }, [socket])  

 return (  
  <div>  
    <button onClick={handleEnterRoom}>Enter Room</button>  
    <button onClick={handleSendMessage}>Send Message</button>  
    <div>Message:</div>  
    <input  
      name="message"  
      value={formData.message}  
      onChange={handleChange}  
      placeholder="Type your message"  
    />  
    <div style={styles.messagesContainer}>  
      {messages.map((msg, index) => (  
        <div key={index} style={styles.messageWrapper(msg.type)}>  
          <div>{msg.message}</div>  
          <div>{msg.userName}</div>  
          <div style={styles.timestamp}>{new Date(msg.timeStamp).toLocaleString()}</div>  
        </div>  
      ))}  
    </div>  
  </div>  
 );  
}  

const styles = {  
  messagesContainer: {  
    width: '520px',  
    height: '520px',  
    border: '1px solid black',  
    overflowY: 'scroll',  
  },  
  messageWrapper: (type) => ({  
    margin: '10px',  
    textAlign: type === 'sent' ? 'right' : 'left',  
  }),  
  timestamp: {  
    fontSize: '12px',  
    color: 'gray',  
  },  
}  

export default App

Тепер ви можете запустити ваш сервер та клієнтський проект за допомогою наступних команд:

npm run dev // Запуск сервера (Node.js)  
npm run start // Запуск клієнта (React.js)

Ви можете протестувати це, відкривши кілька вкладок, різні браузери або вікна інкогніто. Зверніть увагу, що валідація форми ще не реалізована, тому обов'язково вкажіть як номер кімнати, так і ім'я користувача для правильного функціонування.

Приклад сценарію:
- Користувач 1 приєднується до кімнати 1 з ім'ям ‘user1’.
- Користувач 2 приєднується до тієї ж кімнати 1 з ім'ям ‘user2’.
- Коли user1 надсилає повідомлення, воно також відображатиметься у браузері user2, демонструючи комунікацію в реальному часі.

Якщо ця стаття була корисною, будь ласка, поставте «плескання» 👏🏻! Дякую! 😊

Перекладено з: Real-Time Communication with Socket.IO: Integrating React.js and Node.js

Leave a Reply

Your email address will not be published. Required fields are marked *