Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use socket.io event to update state

I have a react functional component:

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

But when i update the state from the socket.socket.on("chatMessage" , I get an error

Can't perform a React state update on an unmounted component

And the socket tells me it took to long to respond, and some recursiveness starts happening.

How should i go about updating my component state from a socket event?

like image 791
TheNormalPerson Avatar asked Oct 27 '25 11:10

TheNormalPerson


1 Answers

You need to setup the socket listner within the useEffect function otherwise on every re-render a new instance will be created and old instances will continue to listen and cause memory overflows and unexpected state update errors. Also do clear your socket listners

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

// P.S. Make sure you are using callback method to update state

like image 163
Shubham Khatri Avatar answered Oct 30 '25 01:10

Shubham Khatri



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!