javascript - 使用房间时清除 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;
关于我需要做什么才能在发送消息时删除输入的任何想法。
我还想尝试重新实现用户:正在输入消息,但这是次要优先级。
任何提示或帮助指向正确的方向将不胜感激。
解决方案
也许您应该使用状态来保存您的输入值,并且您不要为此使用 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,对我来说这是最简单的去抖解决方案之一。
推荐阅读
- python - 将 numpy 数组 (N,M,L) 转换为 (N*L,M+1) ,其中额外的列由整数 [0,...,L-1] 索引
- python - python:从svg文件解析某些值
- sql - 如何借助相似度函数通过确定 PostgreSQL 中一个值与另一个值的相似度来替换值?
- c# - 在 wpf 中绑定 SelectedDates 属性的正确方法是什么?
- javascript - 如何为开放式地图超时添加自定义传单错误处理程序?
- c - 在 C 中使用 mpi 传递多个字符串的数组
- amazon-cognito - 用于 AWS Cognito 中的联合登录的 PostConfirmationTrigger
- python - 将具有 NaN 值的 numpy 数组转换为 1e-9 值,(相干矩阵转换有问题)
- vuejs3 - 子组件 HTML 在 VueJS 中不可见
- javascript - React App:Webpack 无法加载一些结构通用的依赖项