共计 17756 个字符,预计需要花费 45 分钟才能阅读完成。
这篇文章是对于什么的
置信大家对于 web 版的线上聊天室都不生疏,这篇文章次要讲的就是如何应用 Socket.io 和 React 开发一下简略的线上聊天利用。
所谓线上聊天利用,就是你给一个人或者一个群发送一条音讯,他们能够看到这条音讯并且能够回复。既简略又简单。
开发一个聊天室利用,你须要在新信息来到的时候及时的感知到。
通常来说,为了取得服务端的信息,咱们须要发送一个 HTTP 申请。然而如果应用 websockets,服务端可能被动告知你有新的信息到来而不须要客户端发动申请。
在本文中,咱们将利用 Socket.io 提供的实时通信来创立一个开放式聊天应用程序,容许用户在该应用程序上发送和接管来自多个用户的音讯。同时你也将学习到如何检测用户是否在线以及用户什么时候在输出。
💡 为了更好的把握这篇文章讲到的内容,你可能须要先把握对于 React.js 和 Node.js 的基础知识
什么是 Socket.io
Socket.io 是一个非常风行的 JavaScript 库。它容许咱们在浏览器和 Node.js 服务端之间创立一个实时的,双向的通信。它是一个高性能并且牢靠的库,通过优化能够以最小的提早解决大量数据。它遵循 WebSocket 协定并提供更好的性能,比方降级为 HTTP 长链接或者主动重连,这些性能能够帮助咱们构建一个高效的实时的利用。
如何通过 Socket.io 连贯 React.js 利用到 Node.js 服务
在这个章节中,咱们将开始为聊天室利用搭建我的项目环境。您还将学习如何将 Socket.io 增加到 React 和 Node.js 应用程序,并连贯两个开发服务器以通过 Socket.io 进行实时通信。
创立我的项目目录,并创立两个子目录名为 client 和 server
$ mkdir chat-app
$ cd chat-app
$ mkdir client server
进入到 client 目录下,通过终端创立 React.js 我的项目
$ cd client
$ npx create-react-app ./
装置 Socket.io 客户端 API 以及 React Router
$ npm install socket.io-client react-router-dom
从 React 我的项目中删除冗余的文件像是 logo 和 测试文件,像上面一样更新 App.js
文件来显示 Hello World
function App() {
return (
<div>
<p>Hello World!</p>
</div>
);
}
接下来,进入 server 目录下,创立一个 package.json
文件
$ cd server
$ npm init -y
装置 Express.js , CORS , Nodemon , 和 Socket.io 服务端 API
$ npm install express cors nodemon socket.io
创立一个 index.js 文件,作为 web 服务器的入口文件
touch index.js
应用 Express 创立一个简略的 Node.js 服务。当咱们在浏览器拜访 [<http://localhost:4000/api>](<http://localhost:4000/api>)
的时候,上面的代码会返回一个 JSON 对象
//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;
// 新导入的模块
const server = 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 到我的项目中去创立一个实时连贯
// 新导入
const {Server} = require("socket.io");
// 创立实时连贯
const socketIO = new Server(server, {
cors: {origin: "<http://localhost:3000>"}
});
// app.get 代码省略 ...
// 监听连贯
socketIO.on('connection', (socket) => {console.log(`⚡: ${socket.id} 用户已连贯!`);
socket.on('disconnect', () => {console.log('🔥: 一个用户已断开连接');
});
});
从下面的代码中看到,每当用户拜访页面的时候,[socket.io](<http://socket.io/>)("connection")
建设了与 React 利用的连贯,而后为每个 socket 创立一个惟一的 ID,而后将 ID 打印到控制台
当你刷新或者敞开页面,socket 会触发 disconnect 事件,显示一个用户已从 socket 断开链接。
接下来,通过在 package.json
中增加 scripts 启动来配置 Nodemon。代码如下
// 在 server/package.json
"scripts": {
"test": "echo \"Error: no test specified\"&& exit 1",
"start": "nodemon index.js"
},
你能够通过上面的命令来通过 Nodemon 启动服务
$ npm start
关上 client 目录下的 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 服务
// client 目录下运行
$ npm start
在客户端和服务端的服务都启动之后,React 利用的 ID 会显示在服务端的终端上。
祝贺 🥂,React 利用曾经通过 Socket.io 胜利连贯到服务端
💡 对于本文的其余部分,我将疏导你实现为聊天应用程序创立网页以及在 React 应用程序和 Node.js 服务器之间来回发送音讯的过程。我还将领导你如何在收到新音讯时增加主动滚动性能以及如何在你的聊天应用程序中获取沉闷用户
为聊天利用创立主页
在本章节中,咱们将为聊天利用创立一个主页。主页会接管用户名并将其保留到本地存储以供辨认
在 client/src
目录下创立一个名为 components 的目录。而后,创立主页的组件
$ 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"> 登录聊天 </h2>
<label htmlFor="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"> 登录 </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
* {
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;
}
咱们曾经创立了主页,接下来咱们开始设计聊天页面的款式和交互
为利用创立聊天页
在这个章节,咱们将创立聊天界面,容许咱们发送音讯和看到在线用户
从下面的图片能够看到,聊天页面被分成三个局部:ChatBar(侧边栏显示沉闷的用户);ChatBody(蕴含发送的音讯和头部);ChatFooter(蕴含发送输入框和发送按钮)
既然咱们曾经定义了聊天页面的布局,当初能够创立一个这样布局的组件
创立 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;
Char Bar 组件
复制上面的代码到 ChatBar.js
文件中
import React from 'react';
const ChatBar = () => {
return (
<div className="chat__sidebar">
<h2> 自在聊天 </h2>
<div>
<h4 className="chat__header"> 在线用户 </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;
Chat Body 组件
这里咱们创立一个组件来显示曾经发送的音讯和题目
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>
{/* 显示你发送音讯的内容 */}
<div className="message__container">
<div className="message__chats">
<p className="sender__name">You</p>
<div className="message__sender">
<p>Hello there</p>
</div>
</div>
{/* 显示你接管音讯的内容 */}
<div className="message__chats">
<p>Other</p>
<div className="message__recipient">
<p>Hey, I'm good, you?</p>
</div>
</div>
{/* 当有用户正在输出,则被触发 */}
<div className="message__status">
<p>Someone is typing...</p>
</div>
</div>
</>
);
};
export default ChatBody;
Chat Footer 组件
在这里,咱们将在聊天页面底部创立输出和发送按钮。提交表单后,音讯和用户名呈现在控制台中。
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="编写音讯"
className="message"
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
<button className="sendBtn"> 发送 </button>
</form>
</div>
);
};
export default ChatFooter;
在 React 利用和 Socket.io 服务之间发送音讯
在本节中,您将学习如何通过 Socket.io 将音讯从 React 应用程序发送到 Node.js 服务器,反之亦然。要将音讯发送到服务器,咱们须要将 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;
更新 ChatFooter 组件中的 handleSendMessage 函数以将音讯发送到 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 以及 socket 或客户端的音讯事件之前查看文本字段是否为空以及用户名是否存在于本地存储(从主页登录)Node.js 服务器的 ID。
关上服务器的 index.js
文件,更新 Socket.io 相干代码以监听来自 React 应用程序客户端的音讯事件,并将音讯打印到服务器的终端
socketIO.on('connection', (socket) => {console.log(`⚡: ${socket.id} 用户已连贯!`);
// 监听和在控制台打印消
socket.on('message', (data) => {console.log(data);
});
socket.on('disconnect', () => {console.log('🔥: 一个用户已断开连接');
});
});
咱们曾经可能在服务器上检索音讯;因而,让咱们将音讯发送给所有连贯的客户端。
socketIO.on('connection', (socket) => {console.log(`⚡: ${socket.id} 用户已连贯!`);
// 发送信息给到所有在线的用户
socket.on('message', (data) => {socketIO.emit('messageResponse', data);
});
socket.on('disconnect', () => {console.log('🔥: 一个用户已断开连接');
});
});
更新 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 组件以显示在 UI 上
更新 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> 与敌人团聚 </p>
<button className="leaveChat__btn" onClick={handleLeaveChat}>
来到聊天
</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> 有用户正在输出...</p>
</div>
</div>
</>
);
};
export default ChatBody;
下面的代码片段依据是你或是其余用户发送了音讯来显示音讯。绿色的音讯是你发送的音讯,红色的是来自其余用户的音讯。
祝贺 🥂,聊天利用当初能够失常应用了。你能够关上多个 Tab 并将音讯从一个 Tab 发送到另一个 Tab
如何从 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);
// 发送用户名和 socket ID 到 Node.js 服务器
socket.emit('newUser', { userName, socketID: socket.id});
navigate('/chat');
};
return (...)
...
创立一个事件监听器,每当用户退出或来到聊天利用时,它就会更新 Node.js 服务器上的 users 数组。
let users = [];
socketIO.on('connection', (socket) => {console.log(`⚡: ${socket.id} 用户已连贯!`);
socket.on('message', (data) => {socketIO.emit('messageResponse', data);
});
// 监听新用户的退出
socket.on('newUser', (data) => {
// 增加新用户到 users 中
users.push(data);
// console.log(users);
// 发送用户列表到客户端
socketIO.emit('newUserResponse', users);
});
socket.on('disconnect', () => {console.log('🔥: 一个用户已断开连接');
// 当用户下线的时候更新用户列表
users = users.filter((user) => user.socketID !== socket.id);
// console.log(users);
// 发送用户列表到客户端
socketIO.emit('newUserResponse', users);
socket.disconnect();});
});
当有新用户退出聊天利用,socket.on("newUser")
就会被触发。用户的详细信息(Socket ID 和用户名)保留到 users 数组中,并在名为 newUserResponse
的新事件中发送回 React 应用程序
在 socket.io("disconnect")
中,当用户来到聊天应用程序时更新 user
数组,并触发 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> 自在聊天 </h2>
<div>
<h4 className="chat__header"> 在线用户 </h4>
<div className="chat__users">
{users.map((user) => (<p key={user.socketID}>{user.userName}</p>
))}
</div>
</div>
</div>
);
};
export default ChatBar;
useEffect hook 监听从 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(() => {
// 👇️ 每当音讯文字变动,都会往下滚动
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
组件来蕴含一个带有 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>
......
{/* --- 在 JSX 代码的最底部 ----*/}
<div ref={lastMessageRef} />
</div>
</>
);
};
export default ChatBody;
从下面的代码片段来看,lastMessageRef 附加到音讯底部的一个 div 标签,它的 useEffect 有一个依赖项,即 messages 数组。因而,当音讯更改时,lastMessageRef 的 useEffect 会从新渲染。
告诉其他人有用户正在输出
为了在用户输出时告诉其余用户,咱们将在输入框上应用 JavaScript onKeyDown 事件监听器,它会触发一个向 Socket.io 发送音讯的函数,如下所示:
import React, {useState} from 'react';
const ChatFooter = ({socket}) => {const [message, setMessage] = useState('');
const handleTyping = () =>
socket.emit('typing', `${localStorage.getItem('userName')} 正在输出 `);
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="编写音讯"
className="message"
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={handleTyping}
/>
<button className="sendBtn"> 发送 </button>
</form>
</div>
);
};
export default ChatFooter;
在下面的代码片段中,handleTyping 函数会在用户应用 input 输入框键入时触发键入事件。而后,咱们能够在服务器上监听 typing 事件,并通过另一个名为 typingResponse
的事件向其余用户发送蕴含数据的响应
socketIO.on('connection', (socket) => {// console.log(`⚡: ${socket.id} 用户已连贯!`);
// 监听和在控制台打印消息
// socket.on('message', (data) => {// console.log(data);
// socketIO.emit('messageResponse', data);
// });
socket.on('typing', (data) => socket.broadcast.emit('typingResponse', data));
// 监听新用户的退出
// socket.on('newUser', (data) => {
// 增加新用户到 users 中
// users.push(data);
// console.log(users);
// 发送用户列表到客户端
// socketIO.emit('newUserResponse', users);
// });
// ...
});
接下来监听 ChatPage.js
文件中的 typingResponse
事件,将数据传入 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(() => {
// 👇️ 每当音讯文字变动,都会往下滚动
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 是一个十分棒的工具,具备杰出的性能,使咱们可能构建高效的实时应用程序,例如体育网站、拍卖和外汇交易应用程序,当然还有通过在 Web 浏览器和 Node.js 服务器之间创立长久连贯的聊天应用程序
如果你期待在 Node.js 中构建聊天应用程序,Socket.io 可能是一个很好的抉择
你能够在此处找到本教程的源代码:[](https://github.com/zidanDirk/…)https://github.com/zidanDirk/…
参考文章:
- https://dev.to/novu/building-…https://dev.to/novu/building-…
- https://socket.io/