编写一个基于React的聊天室

前言

此前已经编写了一版后端的im,此次就用其作为服务端,可查看参考资料1

代码

使用WebStorm创建React项目

安装依赖包

复制代码
PS C:\learn-demo\front\chatroom> npm install

added 183 packages, and audited 184 packages in 16s

43 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

创建ChatRoom.tsx

复制代码
import React, { useState, ChangeEvent } from 'react';

const ChatRoom: React.FC = () => {
    const [message, setMessage] = useState('');
    const [messages, setMessages] = useState<string[]>([]);
    const [socket, setSocket] = useState<WebSocket | null>(null);
    const [userName, setUserName] = useState('');

    const handleSendMessage = () => {
        if (socket && message) {
            socket.send(message);
            setMessage('');
        }
    };

    const handleConnected = () => {
        if (userName) {
            setUserName(userName);
            createWebSocket(userName);
        }
    };

    const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
        setMessage(event.target.value);
    };

    const handleInputName = (event: ChangeEvent<HTMLInputElement>) => {
        setUserName(event.target.value);
    };

    const createWebSocket = (userName: string) => {
        setMessages(prevMessages => [...prevMessages, `welcome 【${userName}】`])
        if (userName){
            setUserName(userName);
        }else {
            return;
        }
        //关闭已有websocket连接
        if (socket){
            socket.close()
        }
        const newSocket = new WebSocket(`ws://localhost:18080/ws?userName=${userName}`);
        newSocket.onopen = () => {
            console.log('Connected to the WebSocket server');
        };
        newSocket.onmessage = (event: MessageEvent) => {
            setMessages(prevMessages => [...prevMessages, event.data]);
        };

        newSocket.onclose = () => {
            console.log('Disconnected from the WebSocket server');
        };

        setSocket(newSocket);
    }

    return (
        <div>
            <ul>
                {messages.map((msg, index) => (
                    <li key={index}>{msg}</li>
                ))}
            </ul>
            <input
                type="text"
                value={userName}
                onChange={handleInputName}
            />
            <button onClick={handleConnected}>Connected</button>
            <br/>
            <input
                type="text"
                value={message}
                onChange={handleInputChange}
            />
            <button onClick={handleSendMessage}>Send</button>
        </div>
    );
};

export default ChatRoom;

修改main.tsx

复制代码
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import ChatRoom from "./component/ChatRoom.tsx";

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <ChatRoom />
  </StrictMode>,
)

测试

分别以不同用户名(test1、test2、test3)连接websocket,步骤是第一行输入框输入用户名,然后点击Connected按钮

  • test1发送全体消息

第二行输入框输入消息,点击Send按钮

test2、test3均收到消息

  • test1发送消息给test2

test2收到消息

test3未收到消息

调整后端代码

上述消息分不清到底是谁发给用户的,调整下im服务的代码

SendExecutorFactory

java 复制代码
public void onMessage(String sendUserName, String message) {
    IBaseSendExecutor iBaseSendExecutor = Optional.ofNullable(executorConfiguration.getBaseSendExecutorMap()
            .get(webSocketProperties.getCommunicationType())).orElse(new DefaultSendExecutor());
    message = String.format("【%s】: %s", sendUserName, message);
    //包含@发给指定人,否则发给全部人
    if (StringUtils.contains(message, webSocketProperties.getReceiverSeparator())) {
        iBaseSendExecutor.sendToUser(sendUserName, message);
    } else {
        iBaseSendExecutor.sendToAll(sendUserName, message);
    }
}

重新启动服务端,发送消息

页面上重新连接,test1发送全体消息

test2、test3均收到test1的消息

参考资料

1\].[im后端代码](https://gitee.com/learnhistory/im/tree/1.0-test/ "im后端代码") \[2\].[chatroom前端项目](https://gitee.com/learnhistory/front-chatroom "chatroom前端项目")

相关推荐
Johnnyhaha5 分钟前
Docker Compose Pull 超时与代理踩坑记录
前端
烟袅6 分钟前
React 表单的控制欲:什么时候我们真得控制它了,什么时候该放养了?
前端·react.js
不想秃头的程序员8 分钟前
吃透 JS 事件委托:从原理到实战,解锁高性能事件处理方案
前端·面试
AntoineGriezmann9 分钟前
前端 Token 刷新机制实战:基于 Axios 的 accessToken 自动续期方案
前端
烟袅11 分钟前
从定时器管理出发,彻底搞懂防抖与节流的实现逻辑
前端·javascript
UIUV1 小时前
JavaScript 遍历方法详解
前端·javascript·代码规范
Zyx20072 小时前
React 中的 Props:组件通信与复用的核心机制
前端
海云前端12 小时前
大模型Function Calling的函数如何调用的?
前端
ohyeah2 小时前
防抖与节流:前端性能优化的两大利器
前端·javascript