编写一个基于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前端项目")

相关推荐
炫饭第一名1 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
王晓枫2 小时前
flutter接入三方库运行报错:Error running pod install
前端·flutter
符方昊2 小时前
React 19 对比 React 16 新特性解析
前端·react.js
ssshooter2 小时前
又被 Safari 差异坑了:textContent 拿到的值居然没换行?
前端
曲折2 小时前
Cesium-气象要素PNG色斑图叠加
前端·cesium
Forever7_2 小时前
Electron 淘汰!新的桌面端框架 更强大、更轻量化
前端·vue.js
Angelial2 小时前
Vue3 嵌套路由 KeepAlive:动态缓存与反向配置方案
前端·vue.js
jiayu3 小时前
Angular学习笔记24:Angular 响应式表单 FormArray 与 FormGroup 相互嵌套
前端
jiayu3 小时前
Angular6学习笔记13:HTTP(3)
前端
小码哥_常3 小时前
Kotlin抽象类与接口:相爱相杀的编程“CP”
前端