React 和 Socket.io | useState 在输入中生成新的套接字连接 onChange

IT技术 reactjs socket.io onchange
2021-05-08 15:40:42

我正在使用 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;

这是我写的每个字符的输出(我输入了“用户名”)

先感谢您

2个回答

每次更新状态时,App 组件都会渲染,因此变量会再次初始化:

const socket = io.connect('http://localhost:5000');

将初始化移动到 intouseEffect()并在外部声明套接字变量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;

是的,您在每次重新渲染时创建一个新实例,因为您是socket在 App 的顶级范围内定义的。

您已经有一个useEffect挂钩,因此请尝试在该挂钩内启动连接。由于您已将一个空数组作为第二个参数传递给钩子,因此代码只会执行一次(在安装组件时)。