React and Socket.io | useState generates new socket connection onChange in input

折月煮酒 提交于 2019-12-23 19:16:31

问题


I'm using React and Socket.io but I have an issue. Each character I write in the input field, a new socket id is created and I do not want that to happen. When I remove the setUsername(e.target.value) in the onChange method no socket are created. Here is my code:

Server Side:

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));

Client Side:

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')

Thank you in advance


回答1:


Right, you're creating a new instance on every re-render because you're defining socket in the top-level scope of App.

You already have a useEffect hook in place, so try initiating the connection within that hook instead. Since you've passed an empty array as a second argument to the hook, the code will only be executed once (at the time the component is mounted).




回答2:


Every time you update the state, the App component is rendering so the variables are being initialized again:

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

Move the initialization into into useEffect() and declare the socket variable outside App.js, or keep it inside App.js but use a useRef();

useEffect(() => {
    M.AutoInit();

    async function connect () {
           socket = io.connect('http://localhost:5000');
        }
    connect();

  }, []);

Full code:

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;


来源:https://stackoverflow.com/questions/58922995/react-and-socket-io-usestate-generates-new-socket-connection-onchange-in-input

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!