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