Socket.io с экземпляром React Hooks с отслеживанием состояния - PullRequest
0 голосов
/ 16 апреля 2020

Попытка преобразовать демонстрационный ChatApp с помощью Socket.io из компонента класса в функциональный компонент с использованием реакционных хуков. Я хотел бы сохранить имя пользователя, экземпляр сокета, содержимое чата и журнал предыдущих сообщений, используя состояние между рендерами, чтобы клиент не подключался снова и снова с другим Socket.id или пытался печатать без текста. .

Моя проблема в том, что когда я пытаюсь использовать useEffect как componentWillMount, кажется, что он вообще не может сохранить экземпляр socket.io или изменить его состояние, не сделав его непригодным для использования:

Пример:

function myComponent() {
  const [socket, setSocket] = useState("none");

  useEffect(() => {
    setSocket(io('http://127.0.0.1:1000'));
    //but _socket_ is still "none" at this point unfortunately
    socket.on('connection', () => {
      setUsername(socket.id.slice(0, 3))
    })
  }, [])

  //...

В настоящее время код также выполняется в бесконечном l oop, что меньше, чем желательно.

Как сохранить данные между рендерами и только один раз открывать сокеты с крючками?

import React, { useEffect, useState } from 'react'
import Footer from './Footer';

import io from "socket.io-client"
const endpoint = "http://192.168.254.22:1000"

function ChatApp() {
  const [socket, setSocket] = useState("Loading");
  const [username, setUsername] = useState("");
  const [futureMessage, setFutureMessage] = useState("");
  const [messageLog, setMessageLog] = useState([]);


  function initSocket() {
    const new_socket = io(endpoint); //open socket on the URL of our server
    new_socket.on('connect', () => {
      setSocket(new_socket);
      setUsername(new_socket.id.slice(0,3));//first 3 letters of socket ID
    })

    new_socket.on('NEW_MESSAGE', (incoming_username, incoming_message) => {
      let newMessage = <p key={this.state.all_messages.length}><b>{incoming_username}</b>: {incoming_message}</p>;
      setMessageLog(messageLog.push(newMessage));
    })
  }

  useEffect( ()=> {
    initSocket();
  });



  function handleChange(e) {
    setFutureMessage(e.target.value);
  }

  function handleSubmit(e) {
    e.preventDefault();
    socket.emit("NEW_MESSAGE_TO_SERVER", username, futureMessage);
    setFutureMessage(""); //reset message box
  }

  return (
      <div className="standard-window" id="chat-window">
        <div className = "chat-window-title">
          <h1>Test Chat App</h1>
          <p>{socket ? ("Socket ID: " + socket.id):null}</p>
        </div>
        {/*------------------------------------*/}
        <div className = "chat-window-messages">
        {messageLog}
        </div>
        {/*------------------------------------*/}
        <div className = "chat-window-input">
          <form onSubmit = {handleSubmit}>
            <input
              type="text"
              id="message-text-input-field"
              placeholder="Type your message here..."
              onChange={handleChange}
              value={futureMessage}
              />
          </form>
        </div>
        {/*------------------------------------*/}
        <Footer />


      </div>
  )
};

export default ChatApp
...