О чем эта статья?
Мы все сталкивались с общением в Интернете, это может быть Facebook, Instagram, WhatsApp, и этот список можно продолжить.
Для пояснения: вы отправляете сообщение человеку или группе, они видят это сообщение и отвечают вам. Простой, но сложный.
Чтобы разработать приложение для чата, вам нужно быть в курсе новых сообщений, как только они приходят.
Обычно для получения информации с сервера нужно отправить HTTP-запрос. С помощью веб-сокетов сервер сообщает вам, когда появляется новая информация, не спрашивая ее.
В этой статье мы будем использовать связь в реальном времени, предоставляемую Socket.io, для создания приложения открытого чата, которое позволяет пользователям отправлять и получать сообщения от нескольких пользователей в приложении. Вы также узнаете, как определить пользователей, которые находятся в сети, и когда пользователь печатает.
Чтобы прочитать эту статью, вам необходимо иметь базовые знания о React.js и Node.js, чтобы понять эту статью.
Что такое Socket.io?
Socket.io — это популярная библиотека JavaScript, которая позволяет нам создавать двустороннюю связь в режиме реального времени между веб-браузерами и сервером Node.js. Это высокопроизводительная и надежная библиотека, оптимизированная для обработки больших объемов данных с минимальной задержкой.
Он следует протоколу WebSocket и предоставляет улучшенные функциональные возможности, такие как возврат к длительному опросу HTTP или автоматическое повторное подключение, что позволяет нам создавать эффективные приложения для чата и реального времени.
Novu — первая архитектура уведомлений с открытым исходным кодом
Просто краткая справка о нас. Нову — первая инфраструктура уведомлений с открытым исходным кодом. Мы в основном помогаем управлять всеми уведомлениями о продуктах. Это может быть In-App (значок колокольчика, как в Facebook — Websockets), электронная почта, SMS и так далее.
Сейчас мы в тренде на Github, и каждая дополнительная звезда может помочь нам привлечь больше разработчиков, буду рад, если вы поможете мне ❤️
https://github.com/novuhq/novu
Как подключить приложение React.js к Node.js через Socket.io
В этом разделе мы настроим среду проекта для нашего чат-приложения. Вы также узнаете, как добавить Socket.io в приложение React и Node.js и соединить оба сервера разработки для связи в реальном времени через Socket.io.
Создайте папку проекта, содержащую две подпапки с именами client и server.
mkdir chat-app
cd chat-app
mkdir client server
Перейдите в папку клиента через свой терминал и создайте новый проект React.js.
cd client
npx create-react-app ./
Установите клиентский API Socket.io и React Router. React Router — это библиотека JavaScript, которая позволяет нам перемещаться между страницами в приложении React.
npm install socket.io-client react-router-dom
Удалите лишние файлы, такие как логотип и тестовые файлы, из приложения React и обновите файл App.js
, чтобы отобразить Hello World, как показано ниже.
function App() {
return (
<div>
<p>Hello World!</p>
</div>
);
}
Затем перейдите в папку сервера и создайте файл package.json
.
cd server
npm init -y
Установите Express.js, CORS, Nodemon и Socket.io Server API.
Express.js — это быстрый минималистичный фреймворк, предоставляющий несколько функций для создания веб-приложений на Node.js. CORS — это пакет Node.js, который обеспечивает связь между разными доменами.
Nodemon — это инструмент Node.js, который автоматически перезапускает сервер после обнаружения изменений в файле, а Socket.io позволяет нам настроить соединение в реальном времени на сервере.
npm install express cors nodemon socket.io
Создайте файл index.js — точку входа на веб-сервер.
touch index.js
Настройте простой сервер Node.js с помощью Express.js. Приведенный ниже фрагмент кода возвращает объект JSON при посещении http://localhost:4000/api
в браузере.
//index.js const express = require('express'); const app = express(); const PORT = 4000;
app.get('/api', (req, res) => { res.json({ message: 'Hello world', }); });
app.listen(PORT, () => { console.log(`Server listening on ${PORT}`); });
Импортируйте библиотеки HTTP и CORS, чтобы разрешить передачу данных между клиентским и серверным доменами.
const express = require('express'); const app = express(); const PORT = 4000;
//New imports const http = require('http').Server(app); const cors = require('cors');
app.use(cors());
app.get('/api', (req, res) => { res.json({ message: 'Hello world', }); });
http.listen(PORT, () => { console.log(`Server listening on ${PORT}`); });
Затем добавьте Socket.io в проект, чтобы создать соединение в реальном времени. Перед блоком app.get()
скопируйте приведенный ниже код.
//New imports ..... const socketIO = require('socket.io')(http, { cors: { origin: "http://localhost:3000" } });
//Add this before the app.get() block socketIO.on('connection', (socket) => { console.log(`⚡: ${socket.id} user just connected!`); socket.on('disconnect', () => { console.log('🔥: A user disconnected'); }); });
Из приведенного выше фрагмента кода функция socket.io("connection")
устанавливает соединение с приложением React, затем создает уникальный идентификатор для каждого сокета и записывает идентификатор в консоль всякий раз, когда пользователь посещает веб-страницу.
Когда вы обновляете или закрываете веб-страницу, сокет запускает событие разъединения, показывающее, что пользователь отключился от сокета.
Затем настройте Nodemon, добавив команду запуска в список сценариев в файле package.json
. Фрагмент кода ниже запускает сервер с помощью Nodemon.
//In server/package.json
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "nodemon index.js" },
Теперь вы можете запустить сервер с помощью Nodemon, используя приведенную ниже команду.
npm start
Откройте файл App.js в папке клиента и подключите приложение React к серверу Socket.io.
import socketIO from 'socket.io-client'; const socket = socketIO.connect('http://localhost:4000');
function App() { return ( <div> <p>Hello World!</p> </div> ); }
Запустите сервер React.js.
npm start
Проверьте терминал, на котором запущен сервер; ID клиента React.js появится в терминале.
Поздравляем 🥂, приложение React успешно подключено к серверу через Socket.io.
💡 В оставшейся части этой статьи я проведу вас через создание веб-страниц для приложения чата и отправку сообщений туда и обратно между приложением React и сервером Node.js. Я также расскажу вам, как добавить функцию автоматической прокрутки при поступлении нового сообщения и как получить активных пользователей в приложении чата.
Создание домашней страницы для приложения чата
В этом разделе мы создадим домашнюю страницу для приложения чата, которое принимает имя пользователя и сохраняет его в локальном хранилище для идентификации.
Создайте папку с именем компоненты в папке client/src
. Затем создайте компонент домашней страницы.
cd src
mkdir components & cd components
touch Home.js
Скопируйте приведенный ниже код в файл Home.js
. Фрагмент кода отображает ввод формы, который принимает имя пользователя и сохраняет его в локальном хранилище.
import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom';
const Home = () => { const navigate = useNavigate(); const [userName, setUserName] = useState('');
const handleSubmit = (e) => { e.preventDefault(); localStorage.setItem('userName', userName); navigate('/chat'); }; return ( <form className="home__container" onSubmit={handleSubmit}> <h2 className="home__header">Sign in to Open Chat</h2> <label htmlFor="username">Username</label> <input type="text" minLength={6} name="username" id="username" className="username__input" value={userName} onChange={(e) => setUserName(e.target.value)} /> <button className="home__cta">SIGN IN</button> </form> ); };
export default Home;
Затем настройте React Router, чтобы включить навигацию между страницами приложения чата. Для этого приложения достаточно домашней страницы и страницы чата.
Скопируйте приведенный ниже код в файл src/App.js
.
import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Home from './components/Home'; import ChatPage from './components/ChatPage'; import socketIO from 'socket.io-client';
const socket = socketIO.connect('http://localhost:4000'); function App() { return ( <BrowserRouter> <div> <Routes> <Route path="/" element={<Home socket={socket} />}></Route> <Route path="/chat" element={<ChatPage socket={socket} />}></Route> </Routes> </div> </BrowserRouter> ); }
export default App;
Фрагмент кода назначает разные маршруты для домашней страницы и страницы чата приложения с использованием React Router v6 и передает библиотеку Socket.io в компоненты. Мы создадим страницу чата в следующем разделе.
Перейдите в файл src/index.css
и скопируйте приведенный ниже код. Он содержит весь CSS, необходимый для стилизации этого проекта.
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300;400;500;600;700;800;900&display=swap');
* { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Poppins', sans-serif; } .home__container { width: 100%; height: 100vh; display: flex; flex-direction: column; justify-content: center; align-items: center; } .home__container > * { margin-bottom: 10px; } .home__header { margin-bottom: 30px; } .username__input { padding: 10px; width: 50%; } .home__cta { width: 200px; padding: 10px; font-size: 16px; cursor: pointer; background-color: #607eaa; color: #f9f5eb; outline: none; border: none; border-radius: 5px; } .chat { width: 100%; height: 100vh; display: flex; align-items: center; } .chat__sidebar { height: 100%; background-color: #f9f5eb; flex: 0.2; padding: 20px; border-right: 1px solid #fdfdfd; } .chat__main { height: 100%; flex: 0.8; } .chat__header { margin: 30px 0 20px 0; } .chat__users > * { margin-bottom: 10px; color: #607eaa; font-size: 14px; } .online__users > * { margin-bottom: 10px; color: rgb(238, 102, 102); font-style: italic; } .chat__mainHeader { width: 100%; height: 10vh; display: flex; align-items: center; justify-content: space-between; padding: 20px; background-color: #f9f5eb; } .leaveChat__btn { padding: 10px; width: 150px; border: none; outline: none; background-color: #d1512d; cursor: pointer; color: #eae3d2; } .message__container { width: 100%; height: 80vh; background-color: #fff; padding: 20px; overflow-y: scroll; }
.message__container > * { margin-bottom: 10px; } .chat__footer { padding: 10px; background-color: #f9f5eb; height: 10vh; } .form { width: 100%; height: 100%; display: flex; align-items: center; justify-content: space-between; } .message { width: 80%; height: 100%; border-radius: 10px; border: 1px solid #ddd; outline: none; padding: 15px; } .sendBtn { width: 150px; background-color: green; padding: 10px; border: none; outline: none; color: #eae3d2; cursor: pointer; } .sendBtn:hover { background-color: rgb(129, 201, 129); } .message__recipient { background-color: #f5ccc2; width: 300px; padding: 10px; border-radius: 10px; font-size: 15px; } .message__sender { background-color: rgb(194, 243, 194); max-width: 300px; padding: 10px; border-radius: 10px; margin-left: auto; font-size: 15px; } .message__chats > p { font-size: 13px; } .sender__name { text-align: right; } .message__status { position: fixed; bottom: 50px; font-size: 13px; font-style: italic; }
Мы создали домашнюю страницу нашего чат-приложения. Далее давайте разработаем пользовательский интерфейс для страницы чата.
Создание страницы чата приложения
В этом разделе мы создадим интерфейс чата, который позволит нам отправлять сообщения и просматривать активных пользователей.
На изображении выше страница чата разделена на три части: панель чата — боковая панель, показывающая активных пользователей, тело чата, содержащее отправленные сообщения и заголовок, и нижний колонтитул чата — окно сообщения и кнопка отправки.
Поскольку мы смогли определить макет страницы чата, теперь вы можете создать компоненты для дизайна.
Создайте файл ChatPage.js
и скопируйте в него приведенный ниже код. Вам понадобятся компоненты ChatBar, ChatBody и ChatFooter.
import React from 'react'; import ChatBar from './ChatBar'; import ChatBody from './ChatBody'; import ChatFooter from './ChatFooter';
const ChatPage = ({ socket }) => { return ( <div className="chat"> <ChatBar /> <div className="chat__main"> <ChatBody /> <ChatFooter /> </div> </div> ); };
export default ChatPage;
Компонент «Панель чата»
Скопируйте приведенный ниже код в файл ChatBar.js
.
import React from 'react';
const ChatBar = () => { return ( <div className="chat__sidebar"> <h2>Open Chat</h2>
<div> <h4 className="chat__header">ACTIVE USERS</h4> <div className="chat__users"> <p>User 1</p> <p>User 2</p> <p>User 3</p> <p>User 4</p> </div> </div> </div> ); };
export default ChatBar;
Компонент «Тело чата»
Здесь мы создадим интерфейс, отображающий отправленные сообщения и заголовок страницы.
import React from 'react'; import { useNavigate } from 'react-router-dom';
const ChatBody = () => { const navigate = useNavigate();
const handleLeaveChat = () => { localStorage.removeItem('userName'); navigate('/'); window.location.reload(); };
return ( <> <header className="chat__mainHeader"> <p>Hangout with Colleagues</p> <button className="leaveChat__btn" onClick={handleLeaveChat}> LEAVE CHAT </button> </header>
{/*This shows messages sent from you*/} <div className="message__container"> <div className="message__chats"> <p className="sender__name">You</p> <div className="message__sender"> <p>Hello there</p> </div> </div>
{/*This shows messages received by you*/} <div className="message__chats"> <p>Other</p> <div className="message__recipient"> <p>Hey, I'm good, you?</p> </div> </div>
{/*This is triggered when a user is typing*/} <div className="message__status"> <p>Someone is typing...</p> </div> </div> </> ); };
export default ChatBody;
Компонент нижнего колонтитула чата
Здесь мы создадим ввод и кнопку отправки внизу страницы чата. Сообщение и имя пользователя появляются в консоли после отправки формы.
import React, { useState } from 'react';
const ChatFooter = () => { const [message, setMessage] = useState('');
const handleSendMessage = (e) => { e.preventDefault(); console.log({ userName: localStorage.getItem('userName'), message }); setMessage(''); }; return ( <div className="chat__footer"> <form className="form" onSubmit={handleSendMessage}> <input type="text" placeholder="Write message" className="message" value={message} onChange={(e) => setMessage(e.target.value)} /> <button className="sendBtn">SEND</button> </form> </div> ); };
export default ChatFooter;
Отправка сообщений между приложением React и сервером Socket.io
В этом разделе вы узнаете, как отправлять сообщения из приложения React на сервер Node.js и наоборот через Socket.io. Чтобы отправить сообщения на сервер, нам нужно будет передать библиотеку Socket.io в ChatFooter — компонент, который отправляет сообщения.
Обновите файл ChatPage.js
, чтобы передать библиотеку Socket.io в компонент ChatFooter
.
import React from 'react'; import ChatBar from './ChatBar'; import ChatBody from './ChatBody'; import ChatFooter from './ChatFooter';
const ChatPage = ({ socket }) => { return ( <div className="chat"> <ChatBar /> <div className="chat__main"> <ChatBody /> <ChatFooter socket={socket} /> </div> </div> ); };
export default ChatPage;
Обновите функцию handleSendMessage
в компоненте ChatFooter
, чтобы отправить сообщение на сервер Node.js.
import React, { useState } from 'react';
const ChatFooter = ({ socket }) => { const [message, setMessage] = useState('');
const handleSendMessage = (e) => { e.preventDefault(); if (message.trim() && localStorage.getItem('userName')) { socket.emit('message', { text: message, name: localStorage.getItem('userName'), id: `${socket.id}${Math.random()}`, socketID: socket.id, }); } setMessage(''); }; return <div className="chat__footer">...</div>; };
export default ChatFooter;
Функция handleSendMessage
проверяет, пусто ли текстовое поле и существует ли имя пользователя в локальном хранилище (вход с домашней страницы) перед отправкой события сообщения, содержащего введенные пользователем данные, имя пользователя, сгенерированный идентификатор сообщения и сокет или клиент. ID для сервера Node.js.
Откройте файл index.js
на сервере, обновите блок кода Socket.io, чтобы прослушивать событие сообщения от клиента приложения React, и зарегистрируйте сообщение на терминале сервера.
socketIO.on('connection', (socket) => { console.log(`⚡: ${socket.id} user just connected!`);
//Listens and logs the message to the console socket.on('message', (data) => { console.log(data); });
socket.on('disconnect', () => { console.log('🔥: A user disconnected'); }); });
Нам удалось получить сообщение на сервере; следовательно, давайте отправим сообщение всем подключенным клиентам.
socketIO.on('connection', (socket) => { console.log(`⚡: ${socket.id} user just connected!`);
//sends the message to all the users on the server socket.on('message', (data) => { socketIO.emit('messageResponse', data); });
socket.on('disconnect', () => { console.log('🔥: A user disconnected'); }); });
Обновите файл ChatPage.js
, чтобы прослушать сообщение с сервера и отобразить его для всех пользователей.
import React, { useEffect, useState } from 'react'; import ChatBar from './ChatBar'; import ChatBody from './ChatBody'; import ChatFooter from './ChatFooter';
const ChatPage = ({ socket }) => { const [messages, setMessages] = useState([]);
useEffect(() => { socket.on('messageResponse', (data) => setMessages([...messages, data])); }, [socket, messages]);
return ( <div className="chat"> <ChatBar socket={socket} /> <div className="chat__main"> <ChatBody messages={messages} /> <ChatFooter socket={socket} /> </div> </div> ); };
export default ChatPage;
Из приведенного выше фрагмента кода Socket.io прослушивает сообщения, отправленные через событие messageResponse
, и распространяет данные в массив сообщений. Массив сообщений передается в компонент ChatBody
для отображения в пользовательском интерфейсе.
Обновите файл ChatBody.js
, чтобы отобразить данные из массива сообщений.
import React from 'react'; import { useNavigate } from 'react-router-dom';
const ChatBody = ({ messages }) => { const navigate = useNavigate();
const handleLeaveChat = () => { localStorage.removeItem('userName'); navigate('/'); window.location.reload(); };
return ( <> <header className="chat__mainHeader"> <p>Hangout with Colleagues</p> <button className="leaveChat__btn" onClick={handleLeaveChat}> LEAVE CHAT </button> </header>
<div className="message__container"> {messages.map((message) => message.name === localStorage.getItem('userName') ? ( <div className="message__chats" key={message.id}> <p className="sender__name">You</p> <div className="message__sender"> <p>{message.text}</p> </div> </div> ) : ( <div className="message__chats" key={message.id}> <p>{message.name}</p> <div className="message__recipient"> <p>{message.text}</p> </div> </div> ) )}
<div className="message__status"> <p>Someone is typing...</p> </div> </div> </> ); };
export default ChatBody;
Приведенный выше фрагмент кода отображает сообщения в зависимости от того, кто отправил сообщение — вы или другой пользователь. Сообщения, выделенные зеленым цветом, — это те, которые вы отправили, а красным — сообщения от других пользователей.
Поздравляем 🥂, приложение чата теперь работает. Вы можете открывать несколько вкладок и отправлять сообщения из одной в другую.
Как получить активных пользователей из Socket.io
В этом разделе вы узнаете, как получить всех активных пользователей и отобразить их на панели чата приложения чата.
Откройте src/Home.js
и создайте событие, которое прослушивает пользователей, когда они входят в систему. Обновите функцию handleSubmit
, как показано ниже:
import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom';
const Home = ({ socket }) => { const navigate = useNavigate(); const [userName, setUserName] = useState('');
const handleSubmit = (e) => { e.preventDefault(); localStorage.setItem('userName', userName); //sends the username and socket ID to the Node.js server socket.emit('newUser', { userName, socketID: socket.id }); navigate('/chat'); }; return (...) ...
Создайте прослушиватель событий, который обновляет массив пользователей на сервере Node.js всякий раз, когда пользователь присоединяется к приложению чата или покидает его.
let users = [];
socketIO.on('connection', (socket) => { console.log(`⚡: ${socket.id} user just connected!`); socket.on('message', (data) => { socketIO.emit('messageResponse', data); });
//Listens when a new user joins the server socket.on('newUser', (data) => { //Adds the new user to the list of users users.push(data); // console.log(users); //Sends the list of users to the client socketIO.emit('newUserResponse', users); });
socket.on('disconnect', () => { console.log('🔥: A user disconnected'); //Updates the list of users when a user disconnects from the server users = users.filter((user) => user.socketID !== socket.id); // console.log(users); //Sends the list of users to the client socketIO.emit('newUserResponse', users); socket.disconnect(); }); });
socket.on("newUser")
запускается, когда новый пользователь присоединяется к приложению чата. Сведения о пользователе (идентификатор сокета и имя пользователя) сохраняются в массиве users
и отправляются обратно в приложение React в новом событии с именем newUserResponse
.
В socket.io("disconnect")
массив users
обновляется, когда пользователь покидает приложение чата, и событие newUserReponse
запускается для отправки клиенту обновленного списка пользователей.
Далее давайте обновим пользовательский интерфейс ChatBar.js
, чтобы отобразить список активных пользователей.
import React, { useState, useEffect } from 'react';
const ChatBar = ({ socket }) => { const [users, setUsers] = useState([]);
useEffect(() => { socket.on('newUserResponse', (data) => setUsers(data)); }, [socket, users]);
return ( <div className="chat__sidebar"> <h2>Open Chat</h2> <div> <h4 className="chat__header">ACTIVE USERS</h4> <div className="chat__users"> {users.map((user) => ( <p key={user.socketID}>{user.userName}</p> ))} </div> </div> </div> ); };
export default ChatBar;
Хук useEffect прослушивает ответ, отправленный с сервера Node.js, и собирает список активных пользователей. Список отображается в представлении и обновляется в режиме реального времени.
Поздравляем 💃🏻, нам удалось получить список активных пользователей из Socket.io. Далее давайте узнаем, как добавить некоторые интересные функции в приложение чата.
Необязательно: автоматическая прокрутка и уведомление пользователей, когда пользователь вводит текст.
В этом разделе вы узнаете, как добавить функцию автоматической прокрутки при получении нового сообщения и функцию ввода, указывающую, что пользователь печатает.
Функция автоматической прокрутки
Обновите файл ChatPage.js
, как показано ниже:
import React, { useEffect, useState, useRef } from 'react'; import ChatBar from './ChatBar'; import ChatBody from './ChatBody'; import ChatFooter from './ChatFooter';
const ChatPage = ({ socket }) => { const [messages, setMessages] = useState([]); const [typingStatus, setTypingStatus] = useState(''); const lastMessageRef = useRef(null);
useEffect(() => { socket.on('messageResponse', (data) => setMessages([...messages, data])); }, [socket, messages]);
useEffect(() => { // 👇️ scroll to bottom every time messages change lastMessageRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages]);
return ( <div className="chat"> <ChatBar socket={socket} /> <div className="chat__main"> <ChatBody messages={messages} lastMessageRef={lastMessageRef} /> <ChatFooter socket={socket} /> </div> </div> ); };
export default ChatPage;
Обновите компонент ChatBody
, чтобы он содержал элемент для lastMessageRef
.
import React from 'react'; import { useNavigate } from 'react-router-dom';
const ChatBody = ({ messages, lastMessageRef }) => { const navigate = useNavigate();
const handleLeaveChat = () => { localStorage.removeItem('userName'); navigate('/'); window.location.reload(); };
return ( <> <div> ...... {/* --- At the bottom of the JSX element ----*/} <div ref={lastMessageRef} /> </div> </> ); };
export default ChatBody;
Из приведенных выше фрагментов кода lastMessageRef
прикрепляется к тегу div в нижней части сообщений, а его useEffect имеет единственную зависимость — массив сообщений. Итак, когда сообщения изменяются, useEffect для lastMessageRef
перерисовывается.
Уведомлять других, когда пользователь печатает
Чтобы уведомлять пользователей, когда пользователь печатает, мы будем использовать прослушиватель событий JavaScript onKeyDown
в поле ввода, который запускает функцию, которая отправляет сообщение в Socket.io, как показано ниже:
import React, { useState } from 'react';
const ChatFooter = ({ socket }) => { const [message, setMessage] = useState('');
const handleTyping = () => socket.emit('typing', `${localStorage.getItem('userName')} is typing`);
const handleSendMessage = (e) => { e.preventDefault(); if (message.trim() && localStorage.getItem('userName')) { socket.emit('message', { text: message, name: localStorage.getItem('userName'), id: `${socket.id}${Math.random()}`, socketID: socket.id, }); } setMessage(''); }; return ( <div className="chat__footer"> <form className="form" onSubmit={handleSendMessage}> <input type="text" placeholder="Write message" className="message" value={message} onChange={(e) => setMessage(e.target.value)} {/*OnKeyDown function*/} onKeyDown={handleTyping} /> <button className="sendBtn">SEND</button> </form> </div> ); };
export default ChatFooter;
Из приведенного выше фрагмента кода функция handleTyping
вызывает событие typing
всякий раз, когда пользователь вводит текст в текстовое поле. Затем мы можем прослушать событие ввода на сервере и отправить ответ, содержащий данные, другим пользователям через другое событие с именем typingResponse
.
socketIO.on('connection', (socket) => { // console.log(`⚡: ${socket.id} user just connected!`); // socket.on('message', (data) => { // socketIO.emit('messageResponse', data); // });
socket.on('typing', (data) => socket.broadcast.emit('typingResponse', data));
// socket.on('newUser', (data) => { // users.push(data); // socketIO.emit('newUserResponse', users); // });
// socket.on('disconnect', () => { // console.log('🔥: A user disconnected'); // users = users.filter((user) => user.socketID !== socket.id); // socketIO.emit('newUserResponse', users); // socket.disconnect(); // }); });
Затем прослушайте событие typingResponse
в файле ChatPage.js и передайте данные в файл ChatBody.js для отображения.
import React, { useEffect, useState, useRef } from 'react'; import ChatBar from './ChatBar'; import ChatBody from './ChatBody'; import ChatFooter from './ChatFooter';
const ChatPage = ({ socket }) => { // const [messages, setMessages] = useState([]); // const [typingStatus, setTypingStatus] = useState(''); // const lastMessageRef = useRef(null);
// useEffect(() => { // socket.on('messageResponse', (data) => setMessages([...messages, data])); // }, [socket, messages]);
// useEffect(() => { // // 👇️ scroll to bottom every time messages change // lastMessageRef.current?.scrollIntoView({ behavior: 'smooth' }); // }, [messages]);
useEffect(() => { socket.on('typingResponse', (data) => setTypingStatus(data)); }, [socket]);
return ( <div className="chat"> <ChatBar socket={socket} /> <div className="chat__main"> <ChatBody messages={messages} typingStatus={typingStatus} lastMessageRef={lastMessageRef} /> <ChatFooter socket={socket} /> </div> </div> ); };
export default ChatPage;
Обновите файл ChatBody.js
, чтобы отображать статус ввода для пользователей.
<div className="message__status">
<p>{typingStatus}</p>
</div>
Поздравляем, вы только что создали приложение для чата!💃🏻
Не стесняйтесь улучшать приложение, добавляя функцию личных сообщений Socket.io, которая позволяет пользователям создавать частные чаты и прямой обмен сообщениями, используя библиотеку аутентификации для авторизации и аутентификации пользователей и базу данных в реальном времени для хранения.
Заключение
Socket.io — отличный инструмент с отличными функциями, который позволяет нам создавать эффективные приложения в реальном времени, такие как веб-сайты для ставок на спорт, приложения для аукционов и торговли на рынке Форекс, и, конечно же, приложения для чата, создавая прочные соединения между веб-браузерами и сервером Node.js. .
Если вы хотите создать чат-приложение на Node.js, Socket.io может стать отличным выбором.
Вы можете найти исходный код этого руководства здесь: https://github.com/novuhq/blog/tree/main/open-chat-app-with-socketIO
Следующая статья
В следующей части цикла я расскажу о подключении чат-приложения к браузерным уведомлениям (web-push), чтобы вы могли информировать пользователей о новых сообщениях, если они не в сети.
Выручи меня!
Если вы считаете, что эта статья помогла вам лучше понять WebSockets! Я был бы очень рад, если бы вы могли дать нам звезду! И дайте мне знать в комментариях ❤️
https://github.com/novuhq/novu
Спасибо за чтение!
Станьте компонуемым: создавайте приложения быстрее, как Lego
Bit – это инструмент с открытым исходным кодом для модульного и совместного создания приложений. Перейдите на компоновку, чтобы поставлять быстрее, более последовательно и легко масштабировать.
Создавайте приложения, страницы, пользовательский опыт и пользовательские интерфейсы как автономные компоненты. Используйте их, чтобы быстрее создавать новые приложения и возможности. Используйте любой фреймворк и инструмент в своем рабочем процессе. Делитесь, повторно используйте и сотрудничайте, чтобы строить вместе.
Помогите своей команде:
→ Совместное использование кода и повторное использование
→ Монорепо