我正在使用React和Socket.io,但是有一个问题。我在输入字段中写入的每个字符都会创建一个新的套接字ID,但我不希望发生这种情况。当我在onChange方法中删除setUsername(e.target.value)时,不会创建套接字。这是我的代码:
服务器端:
const express = require('express'),
app = express(),
http = require('http').createServer(app),
PORT = 5000,
io = require('socket.io')(http);
io.on('connection', (socket) => {
console.log('New client with id: ' + socket.id);
socket.on('disconnect', () => console.log('Disconnected'));
});
http.listen(PORT, (req, res) => console.log('Server has started on port: ' + PORT));
客户端:
import React, { useEffect, useState } from 'react';
import './App.css';
import io from 'socket.io-client';
import 'materialize-css/dist/css/materialize.min.css';
import M from "materialize-css";
function App() {
const socket = io.connect('http://localhost:5000');
const [username, setUsername] = useState('');
useEffect(() => {
M.AutoInit();
//eslint-disable-next-line
}, []);
const handleSubmit = e => {
e.preventDefault();
};
const onChange = e => {
setUsername(e.target.value);
}
return (
<div>
<form onClick={e => handleSubmit(e)}>
<input id="name" placeholder="Username..." onChange={e => onChange(e)} required />
<button type="submit">Submit</button>
</form>
</div>
);
}
export default App;
Here is the output for each character I write (I typed 'username')
提前谢谢您
对,您是在每次重新渲染时都创建一个新实例,因为您是在App的顶级范围内定义socket
。
您已经有一个useEffect
钩子,因此请尝试在该钩子中启动连接。由于您已将一个空数组作为第二个参数传递给该挂钩,因此该代码将仅执行一次(在安装组件时)。
每次更新状态时,App组件都会呈现,因此会再次初始化变量:
const socket = io.connect('http://localhost:5000');
将初始化移至useEffect()
并在App.js
外部声明套接字变量,或将其保留在App.js中,但使用useRef()
;
useEffect(() => {
M.AutoInit();
async function connect () {
socket = io.connect('http://localhost:5000');
}
connect();
}, []);
完整代码:
let socket = null;
function App() {
const [username, setUsername] = useState('');
useEffect(() => {
M.AutoInit();
async function connect () {
socket = io.connect('http://localhost:5000');
}
connect();
}, []);
const handleSubmit = e => {
e.preventDefault();
};
const onChange = e => {
setUsername(e.target.value);
}
return (
<div>
<form onClick={e => handleSubmit(e)}>
<input id="name" placeholder="Username..." onChange={e => onChange(e)} required />
<button type="submit">Submit</button>
</form>
</div>
);
}
export default App;