react中使用 websocket,使用socket.io库
参考官网地址: https://socket.io/zh-CN/docs/v4/client-installation/#from-npm
1.安装
npm install socket.io-client
2.示例代码
import React, { useEffect, useRef, useState } from "react";
import classNames from "classnames";
import { formatDate } from "../../utils/format";
import "./index.css";
// https://socket.io/zh-CN/docs/v4/client-installation/#from-npm
import { io } from "socket.io-client";
const socket = io("ws://localhost:8888"); // 连接,握手
function Chat() {
// 用户列表
const [usersList, setUsersList] = useState([]);
// 历史记录
const [historyData, setHistoryData] = useState([]);
// 当前用户是否是自己
const [mine, setMine] = useState("");
// 要发送的消息
const [message, setMessage] = useState("");
useEffect(() => {
// 当前聊天室的用户数组 -- 有新用户进入/老用户退出/自己进入
socket.on("$updateUser", (users) => {
console.log(users, "users");
setUsersList(users);
});
// 分配的用户名称 -- 自己进入
socket.on("$name", (name) => {
console.log(name, "name");
setMine(name);
});
// 历史聊天记录 -- 自己进入
socket.on("$history", (history) => {
console.log(history, "history");
setHistoryData(history);
});
// 其他人发送消息
socket.on("$message", (message) => {
console.log(message, 123);
setHistoryData([...historyData, message]);
});
return () => {
socket.off("$updateUser");
socket.off("$name");
socket.off("$history");
socket.off("$message");
};
}, [historyData]);
const chatAreaRef = useRef();
// 当聊天区高度超出后,设置滚动条在最下面
useEffect(() => {
chatAreaRef.current.scrollTop = chatAreaRef.current.scrollHeight;
}, [historyData]);
// 发送消息
const handleKeyDown = (e) => {
if (e.key === "Enter") {
e.preventDefault(); // 阻止默认的换行行为
const content = message.trim();
if (!content) return;
const messageInfo = {
name: mine,
content: content,
data: Date.now(),
};
setHistoryData([...historyData, messageInfo]); // 将消息添加到历史记录里面
socket.emit("$message", message); // 将消息发送到服务器
setMessage(""); // 清空textarea
}
};
return (
<section className="chat-container">
<aside className="chat-users">
<div className="title">聊天室成员</div>
{usersList.length > 0 &&
usersList.map((item, index) => (
<div key={index} className="per-user">
{item}
</div>
))}
</aside>
<section className="chat-main">
<div className="chat-user">{mine}</div>
<div className="chat-area" ref={chatAreaRef}>
{historyData.length > 0 &&
historyData.map((item, index) => (
<div
key={index}
className={classNames("chat-item", {
mine: mine === item.name,
})}
>
<div className="name">{item.name}</div>
<div className="content">{item.content}</div>
<div className="date">{formatDate(item.date)}</div>
</div>
))}
</div>
<div className="chat-message">
<textarea
name="message"
value={message}
onChange={(e) => {
setMessage(e.target.value);
}}
onKeyDown={handleKeyDown}
></textarea>
</div>
</section>
</section>
);
}
export default Chat;
3.效果: