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

相关推荐
IT_陈寒1 小时前
Vue3性能优化实战:这5个技巧让我的应用加载速度提升了70%
前端·人工智能·后端
树上有只程序猿1 小时前
react 实现插槽slot功能
前端
stoneship2 小时前
Web项目减少资源加载失败白屏问题
前端
DaMu2 小时前
Cesium & Three.js 【移动端手游“户外大逃杀”】 还在“画页面的”前端开发小伙伴们,是时候该“在往前走一走”了!我们必须摆脱“画页面的”标签!
前端·gis
非专业程序员2 小时前
一文读懂Font文件
前端
Asort2 小时前
JavaScript 从零开始(七):函数编程入门——从定义到可重用代码的完整指南
前端·javascript
Johnny_FEer2 小时前
什么是 React 中的远程组件?
前端·react.js
我是日安2 小时前
从零到一打造 Vue3 响应式系统 Day 10 - 为何 Effect 会被指数级触发?
前端·vue.js
知了一笑2 小时前
「AI」网站模版,效果如何?
前端·后端·产品