【问题标题】:use socket.io event to update state使用 socket.io 事件更新状态
【发布时间】:2020-07-17 10:07:24
【问题描述】:

我有一个反应功能组件:

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" 更新状态时,我得到一个错误

无法对未安装的组件执行 React 状态更新

并且套接字告诉我响应需要很长时间,并且开始发生一些递归。

我应该如何从套接字事件更新我的组件状态?

【问题讨论】:

    标签: javascript reactjs socket.io react-functional-component


    【解决方案1】:

    您需要在 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>
      );
    }
    

    //确保您正在使用回调方法来更新状态

    【讨论】:

    • 谢谢,它成功了,我是新来的钩子。但是为什么组件会卸载呢?为什么返回一个关闭监听器的函数会消除错误?
    • 该错误有时会产生误导。但是,如果即使组件不再呈现,您也不清除您的侦听器,侦听器将继续执行并尝试为不存在的组件设置状态
    【解决方案2】:

    套接字是副作用。

    useEffecf(() => {
      const callback =  (msg) => {
        setMessages([...messages, msg]);
      };
    
      socket.socket.on("chatMessage", callback);
    
      return () => {
        socket.socket.off("chatMessage", callback);
      };
    }, []);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-29
      • 2020-12-01
      • 2021-02-14
      • 2021-11-24
      • 1970-01-01
      • 2012-07-31
      • 2019-10-04
      相关资源
      最近更新 更多