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

相关推荐
Asort14 分钟前
JavaScript 从零开始(六):控制流语句详解——让代码拥有决策与重复能力
前端·javascript
无双_Joney33 分钟前
[更新迭代 - 1] Nestjs 在24年底更新了啥?(功能篇)
前端·后端·nestjs
在云端易逍遥35 分钟前
前端必学的 CSS Grid 布局体系
前端·css
ccnocare36 分钟前
选择文件夹路径
前端
艾小码36 分钟前
还在被超长列表卡到崩溃?3招搞定虚拟滚动,性能直接起飞!
前端·javascript·react.js
闰五月37 分钟前
JavaScript作用域与作用域链详解
前端·面试
泉城老铁41 分钟前
idea 优化卡顿
前端·后端·敏捷开发
前端康师傅41 分钟前
JavaScript 作用域常见问题及解决方案
前端·javascript
司宸42 分钟前
Prompt结构化输出:从入门到精通的系统指南
前端