首页 > 解决方案 > 使用房间时清除 Socket React 应用程序中的消息输入

问题描述

我正在开发一个反应应用程序,在按照房间教程进行操作后,我无法再在输入消息时清除输入。注释掉的部分是我尝试过的东西。我想我想做的事情以某种方式引用 socket.js 文件中的 messageRef 并将其设置为空字符串。或者,我想我可能想将房间功能移动到 Chat.js,但我学会设置它的方式是在一个单独的文件中。

对于客户端,我在 utils 文件夹中有这个 Chat.js 组件和 socket.js

import React, { useEffect, useState, useRef } from "react";
import {initiateSocket, disconnectSocket, subscribeToChat, handleTyping, sendMessage } from "../../utils/socket/socket";
import "./listStyle.css";
var user = "User";
var store = "Store"
var storeMessage = user + " is going to " + store;


function Chat() {
    const rooms = ['1', '2'];
    let messageRef = useRef();
    const [room, setRoom] = useState(rooms[0]);
    const [typing, setTyping] = useState("")
    const [message, setMessage] = useState("");
    const [chat, setChat] = useState([]);
    //keeps inputing for every letter
    // const clearInput = (input) =>
    // {
    //     //input = "";
    //     console.log("input cleared")
    // }
    // const handleSendMessage = () => {
    //     sendMessage(room, user + ": " + messageRef.current.value)
    //     messageRef.current.value = "";
    // }
    //const handleTyping = () => { socket.emit("typing", user + ": is typing") }
    useEffect(() => {
        if (room) initiateSocket(room);
        subscribeToChat((err, data) => {
            if (err) return;
            setChat(oldChats => [...oldChats, data])
            setTyping("")
        });
        return () => {
            disconnectSocket();
        }
    }, [room]);
    return (
        <div>
            <h1>Group: {room}</h1>
            { rooms.map((r, i) =>
                <button onClick={() => setRoom(r)} key={i}>{r}</button>)}
            <h1>{storeMessage}</h1>
            <div id="list-chat">
                <div id="chat-window">
                    <div id="output" >
                        {chat.map((m, i) => <p key={i}>{m}</p>)}
                    </div>
                    <div id="feedback" >{typing}</div>
                </div>
                <input id="message" autoComplete="off" type="text" 
                defaultValue = ""
                 placeholder="message"
                //value={message}
                    onChange={() => setMessage(messageRef.current.value)} ref={messageRef}
                    //onChange={() => handleTyping(room, user + ": is typing.")}
                    />
                <button id="send" 
                onClick={() => sendMessage(room, user + ": " + messageRef.current.value)} 
                //onClick={() => console.log("test")}
                //onClick={() => sendMessage(room, user + ": " + messageRef.current.value)} 
                //onchange={e => messageRef.current.value = ""}
                //onClick={handleSendMessage()}
                //onChange={() => handleTyping(room, user + ": is typing." )}
                //only clears current room
                //have to comment out on startup
                //onChange={console.log("test")}
                //onSubmit={messageRef.current.value = ""}
                    >Send</button>
            </div>
        </div>
    )
}

export default Chat;

socket.js 使用 sendMessage 函数发送消息

(这 3 个是在房间实施之前

// import {io} from "socket.io-client";
// const socket = io.connect(process.env.PORT || "http://localhost:3001");
// export default socket;

import io from 'socket.io-client';
let socket;
export const initiateSocket = (room) => {
  socket = io('http://localhost:3000');
  console.log(`Connecting socket...`);
  if (socket && room) socket.emit('join', room);
}
export const disconnectSocket = () => {
  console.log('Disconnecting socket...');
  if(socket) socket.disconnect();
}
export const subscribeToChat = (cb) => {
  if (!socket) return(true);
  socket.on('chat', msg => {
    console.log('Websocket event received!');
    return cb(null, msg);
  });
}
export const handleSendMessage = () =>{
    
}
export const sendMessage = (room, message) => {
  if (socket) socket.emit('chat', {room, message });
  console.log("message sent")
  //message = "";
}
export const handleTyping = (room, message) =>{
    if (socket) socket.emit('typing', {room, message});
    //message = "";
    console.log("typing")
}

和我的服务器端文件(与实际的 server.js 分开)

const socketio = require('socket.io');

//let rooms = ["room1", "room2"] 

const initializeSocketio = (server) => {
    const io = socketio(server, {
        cors: {
            origin: "http://localhost:3000",
            methods: ["GET", "POST"],
            allowedHeaders: ["my-custom-header"],
            credentials: true
        }
    });
    io.on('connection', function (socket) {
        console.log("made socket connection", socket.id)

        // socket.on('chat', function (data) {
        //     io.sockets.emit('chat', data)
        // });
        //doesn't do anything right now
        // socket.on('start-shop', function (data) {
        //     io.sockets.emit('start-shop', data)
        // });

        // socket.on('typing', function (data) {
        //     socket.broadcast.emit('typing', data)
        // });
        //room test
        // room1 = "room1";
        // socket.on('join1', function (room1) {
        //     //socket.join(room1);
        //     console.log(room1)
        // });
        // room2 = "room2";
        // socket.on('join2', function (room2) {
        //     //socket.join(room2);
        //     console.log(room2)
        // });
        //socket.in(room).emit('message', 'what is going on, party people?');
        // socket.in('foobar').emit('message', 'anyone in this room yet?');
        socket.on('disconnect', () =>
            console.log(`Disconnected: ${socket.id}`));
        socket.on('join', (room) => {
            console.log(`Socket ${socket.id} joining ${room}`);
            socket.join(room);
        });
        socket.on('chat', (data) => {
            const { message, room } = data;
            console.log(`msg: ${message}, room: ${room}`);
            io.to(room).emit('chat', message);
        });
        // socket.on('typing', (data) => {
        //     const { typing, room } = data;
        //     console.log(`msg: ${typing}, room: ${room}`);
        //     io.to(room).broadcast('typing', typing);
        // });
    });
}

module.exports = initializeSocketio;

在我实现房间之前,我使用的是 List.js,当消息在 handleSentMessage 函数中发送并且它起作用时,它确实删除了输入。

import React, { useEffect, useState, useRef } from "react";
import socket from "../../utils/socket/socket";
import "./listStyle.css";
var user = "User";
var store = "Store"
var storeMessage = user + " is going to " + store;
//room test
var room1 = "room1";
var room2 = "room2";

function List() {
    const messageRef = useRef();
    const [messages, setMessages] = useState([]);
    const [typing, setTyping] = useState("")
    const [room, setRoom] = useState("");
    const handleSendMessage = () => {
        socket.emit("chat", user + ": " + messageRef.current.value)
        messageRef.current.value = ""
    }
    //room test
    //connect room 1
    const connectRoom1 = () => {
        console.log("button 1 clicked")
        // socket.on('join1', function (room1) {
        //     socket.emit('room1', room1)
        //     console.log("connected to room1")
        //     //need to do something with this
        //     setRoom()
        // });
        socket.emit('join1', "anything1")
    }
    //connect room 2
    const connectRoom2 = () => {
        // console.log("button 2 clicked")
        // socket.on('join2', function () {
        //     socket.emit('room2', room2)
        //     console.log("connected to room2")
        //     //need to do something with this
        //     setRoom()
        // });
        socket.emit('join2', "anything2")
    }
    //commented out for now
    // socket.on('connect', function(){
    //     socket.emit('room1', room1)
    // });
    // socket.on('connect', function(){
    //     socket.emit('room2', room2)
    // });
    //room test
    socket.on('message', function (data) {
        console.log('Incoming message:', data);
    });
    const handleTyping = () => { socket.emit("typing", user + ": is typing") }
    useEffect(() => {
        socket.on("chat", (data) => {
            setMessages((prevMessages) => ([...prevMessages, data]));
            setTyping("")
        });
        socket.on("typing", (data) => {
            setTyping(data)
            console.log(data)
        });
        return () => {
            socket.off("chat");
        }
        // dependency array, put user object in array if we want the callback function to fire everytime userobject sees a change
    }, [])
    return (
        <div>
            {/* connect to room 1 */}
            <button onClick={connectRoom1}> Room 1 </button>
            <br></br>
            {/* connect to room 2 */}
            <button onClick={connectRoom2}> Room 2 </button>
            <h1>{storeMessage}</h1>
            <div id="list-chat">
                <div id="chat-window">
                    <div id="output">
                        {messages.map((message, i) => (
                            <p key={i}>{message}</p>
                        ))}
                    </div>
                    <div id="feedback">{typing}</div>

                </div>
                <input id="message" autoComplete="off" type="text" placeholder="message" ref={messageRef} onChange={handleTyping} />
                <button id="send" onClick={handleSendMessage}>Send</button>
            </div>
        </div>
    )
}

export default List;

关于我需要做什么才能在发送消息时删除输入的任何想法。

我还想尝试重新实现用户:正在输入消息,但这是次要优先级。

任何提示或帮助指向正确的方向将不胜感激。

标签: javascriptreactjssocket.io

解决方案


也许您应该使用状态来保存您的输入值,并且您不要为此使用 ref,请尝试以下操作:

const [inputValue, setInputValue] = useState("")
const handleSendMessage = (e) => {
        socket.emit("chat", user + ": " + e.target.value)
        setInputValue("")
       
    }

....

  <input id="message" autoComplete="off" type="text" placeholder="message" 
   ref={messageRef} onChange={handleTyping} value={inputValue}/>

对于打字功能,我建议进行去抖动,以避免发出不必要的事件。看看https://github.com/xnimorz/use-debounce,对我来说这是最简单的去抖解决方案之一。


推荐阅读