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

Posted

技术标签:

【中文标题】React 和 Socket.io | useState 在输入中生成新的套接字连接 onChange【英文标题】:React and Socket.io | useState generates new socket connection onChange in input 【发布时间】:2020-03-14 07:41:22 【问题描述】:

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

提前谢谢你

【问题讨论】:

【参考方案1】:

每次更新状态时,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;

【讨论】:

嗨塞缪尔,希望你很好,你能看看这个问题。非常感谢您的帮助。***.com/questions/65759907/…【参考方案2】:

没错,您在每次重新渲染时都创建了一个新实例,因为您在 App 的***范围内定义了 socket

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

【讨论】:

以上是关于React 和 Socket.io | useState 在输入中生成新的套接字连接 onChange的主要内容,如果未能解决你的问题,请参考以下文章

socket.io 广播不适用于 React

React + Sails + Socket.io

无法在 Node.JS 和 React-Native (Socket.IO) 之间建立连接

Socket.io - React:如何在 React 中检索保存的 socket.io 数据(MongoDB)?

在 react 和 node 中设置 socket io

是否可以将 React Native 与 socket.io 结合使用