использовать событие socket.io для обновления состояния - PullRequest
1 голос
/ 05 апреля 2020

У меня есть функциональный компонент реагирования:

function Chat(props) {
  const [messages, setMessages] = useState([]);

  const inputRef = useRef();

  //The socket is a module that exports the actual socket.io socket
  socket.socket.on("chatMessage", (msg) => {
    setMessages([...messages, msg]);
  });

  const inputChanged = (e) => {
    if (e.key === "Enter") {
      socket.sendMessage(inputRef.current.value)
        .then(() => {
          //do something
        })
        .catch(console.log);
      inputRef.current.value = "";
    }
  };

  return (
      <div>
        {messages.map((msg, i) => <ChatMessage key={i}>{msg}</ChatMessage>)}
        <input ref={inputRef} onKeyPress={inputChanged} />
     </div>
  );
}

Но когда я обновляю состояние из socket.socket.on("chatMessage", я получаю ошибку

Невозможно выполнить реакцию обновление состояния на не смонтированном компоненте

И сокет сообщает мне, что на ответ ушло много времени, и начинает происходить некоторая рекурсивность.

Как мне go сообщить об обновлении состояния моего компонента из события сокета?

Ответы [ 2 ]

2 голосов
/ 05 апреля 2020

Вам необходимо настроить список сокетов в функции useEffect, иначе при каждом повторном рендеринге будет создаваться новый экземпляр, а старые экземпляры будут продолжать прослушивать и вызывать переполнение памяти и непредвиденные ошибки обновления состояния. Также очистите списки сокетов

function Chat(props) {
  const [messages, setMessages] = useState([]);

  const inputRef = useRef();

  useEffect(() => {
      //The socket is a module that exports the actual socket.io socket
      const addMessage = (msg) => setMessages(prevMessages => [...prevMessages, msg]);
      socket.socket.on("chatMessage", addMessage)
      () => {
            // turning of socket listner on unmount
          socket.off('chatMessage', addMessage);
       }
  }, [])

  const inputChanged = (e) => {
    if (e.key === "Enter") {
      socket.sendMessage(inputRef.current.value)
        .then(() => {
          //do something
        })
        .catch(console.log);
      inputRef.current.value = "";
    }
  };

  return (
      <div>
        {messages.map((msg, i) => <ChatMessage key={i}>{msg}</ChatMessage>)}
        <input ref={inputRef} onKeyPress={inputChanged} />
     </div>
  );
}

// PS Убедитесь, что вы используете метод обратного вызова для обновления состояния

0 голосов
/ 05 апреля 2020

Гнездо является побочным эффектом.

useEffecf(() => {
  const callback =  (msg) => {
    setMessages([...messages, msg]);
  };

  socket.socket.on("chatMessage", callback);

  return () => {
    socket.socket.off("chatMessage", callback);
  };
}, []);
...