编辑:我想使这个问题尽可能简洁,以免引起人们阅读时间的浪费。本质上,问题似乎出在我的Chat.js中。似乎启动套接字连接的useEffect搞砸了useEffect,试图从后端读取用户名。我相信我的问题取决于无法调用read()方法。因此,如果有人知道我的问题是使用useEffect获取数据的策略,那么我认为这将回答我的问题。
useEffect(() => {
const abortController = new AbortController()
const signal = abortController.signal
console.log(match.params.userId )
read({
userId: match.params.userId
}, {t: jwt.token}, signal).then((data) => {
setValues({...values, user: data, following: following})
})
return function cleanup(){
abortController.abort()
}
}, [match.params.userId])
console.log(values)
useEffect(() => {
socket = io(ENDPOINT);
setRoom(room);
setName(name);
socket.emit('join', { name, room }, (error) => {
if(error) {
alert(error);
}
});
}, [ENDPOINT, location.search]);
原始问题: 我一直在尝试找到一种以编程方式将数据发送到后端Websocket服务器的方法。我希望用户能够单击我的聊天窗口并立即使用其现有帐户凭据登录。
现在,我有一个Join.js页面“ / chatroom”,用户可以在其中输入其姓名和房间。
import React, { useState, useEffect } from 'react';
import { Link } from "react-router-dom";
import {read} from '../../user/api-user.js'
import auth from '../../auth/auth-helper'
import './Join.css';
export default function SignIn(props) {
const [name, setName] = useState('');
const [room, setRoom] = useState('');
const [values, setValues] = useState({
user: '',
redirectToSignin: false,
})
const jwt = auth.isAuthenticated()
useEffect(() => {
const abortController = new AbortController()
const signal = abortController.signal
read({
userId: props.match.params.userId
}, {t: jwt.token}, signal).then((data) => {
if (data && data.error) {
setValues({...values,redirectToSignin: true})
} else {
var c = {...values, user:data}
setValues(c)
}
})
return function cleanup(){
abortController.abort()
}
}), []
console.log(values.user.name)
const myname = values.user.name
return (
<div className="joinOuterContainer">
<div className="joinInnerContainer">
<h1 className="heading">Join</h1>
<div>
<input placeholder="Name" className="joinInput" type="text" onChange={(event) => setName(event.target.value)} />
</div>
<div>
<input placeholder="Room" className="joinInput mt-20" type="text" onChange={(event) => setRoom(event.target.value)} />
</div>
<Link onClick={e => (!name || !room) ? e.preventDefault() : null} to={`/chat?name=${name}&room=${room}`}>
<button className={'button mt-20'} type="submit">Sign In</button>
</Link>
</div>
</div>
);
}
我还有一个Chat.js“ / chat”页面,在该页面中收集数据并启动与套接字的通信。
import React, { useState, useEffect } from "react";
import queryString from 'query-string';
import io from "socket.io-client";
import TextContainer from '../TextContainer/TextContainer';
import Messages from '../Messages/Messages';
import InfoBar from '../InfoBar/InfoBar';
import Input from '../Input/Input';
import './Chat.css';
let socket;
const Chat = ({ match }) => {
const [name, setName] = useState('');
const [room, setRoom] = useState('');
const [users, setUsers] = useState('');
const [message, setMessage] = useState('');
const [messages, setMessages] = useState([]);
const ENDPOINT = 'http://localhost:3000/';
useEffect(() => {
const { name, room } = queryString.parse(location.search);
socket = io(ENDPOINT);
setRoom(room);
setName(name)
socket.emit('join', { name, room }, (error) => {
if(error) {
alert(error);
}
});
}, [ENDPOINT, location.search]);
useEffect(() => {
socket.on('message', message => {
setMessages(messages => [ ...messages, message ]);
});
socket.on("roomData", ({ users }) => {
setUsers(users);
});
}, []);
const sendMessage = (event) => {
event.preventDefault();
if(message) {
socket.emit('sendMessage', message, () => setMessage(''));
}
}
return (
<div className="outerContainer">
<div className="container">
<InfoBar room={room} />
<Messages messages={messages} name={name} />
<Input message={message} setMessage={setMessage} sendMessage={sendMessage} />
</div>
<TextContainer users={users}/>
</div>
);
}
export default Chat;
我还有一个后端chat.controller.js,可以解析来自套接字的数据:
const users = [];
const addUser = ({ id, name, room }) => {
name = name.trim().toLowerCase();
room = room.trim().toLowerCase();
const existingUser = users.find((user) => user.room === room && user.name === name);
if(!name || !room) return { error: 'Username and room are required.' };
if(existingUser) return { error: 'Username is taken.' };
const user = { id, name, room };
users.push(user);
return { user };
}
const removeUser = (id) => {
const index = users.findIndex((user) => user.id === id);
if(index !== -1) return users.splice(index, 1)[0];
}
const getUser = (id) => users.find((user) => user.id === id);
const getUsersInRoom = (room) => users.filter((user) => user.room === room);
export default {
addUser,
removeUser,
getUser,
此函数是从另一个文件chatcha.controller.js调用的,该文件与后端的套接字进行通信。
import chatCtrl from '../controllers/chat.controller'
export default (server) => {
const io = require('socket.io').listen(server)
io.on('connect', (socket) => {
socket.on('join', ({ name, room }, callback) => {
const { error, user } = chatCtrl.addUser({ id: socket.id, name, room });
if(error) return callback(error);
socket.join(user.room);
socket.emit('message', { user: 'admin', text: `${user.name}, welcome to room ${user.room}.`});
socket.broadcast.to(user.room).emit('message', { user: 'admin', text: `${user.name} has joined!` });
io.to(user.room).emit('roomData', { room: user.room, users: chatCtrl.getUsersInRoom(user.room) });
callback();
});
socket.on('sendMessage', (message, callback) => {
const user = chatCtrl.getUser(socket.id);
io.to(user.room).emit('message', { user: user.name, text: message });
callback();
});
socket.on('disconnect', () => {
const user = chatCtrl.removeUser(socket.id);
if(user) {
io.to(user.room).emit('message', { user: 'Admin', text: `${user.name} has left.` });
io.to(user.room).emit('roomData', { room: user.room, users: chatCtrl.getUsersInRoom(user.room)});
}
})
});
}
我的目标是想出一种方法,让用户单击我的UI中的“聊天”按钮,而不必填写表单-基本上绕过Join.js,立即路由到Chat.js。
我衷心感谢您花时间阅读我的问题,并希望收到社区的回音。