一旦收到来自 socket.io 的消息,useEffect 运行两次

useEffect runs twice once recieve message from socket.io

我正在使用 React、Express 和 socket.io 构建一个简单的聊天应用程序。

每次客户端向服务器发送消息时,服务器都会将消息广播回给每个用户。从后端服务器接收回消息时出现问题。

每次用户收到消息时,useEffect 将 运行 两次而不是一次。

useEffect(() => {
    socket.on("broadcast_msg", (data) => {
      setMsg((list) => [...list, data]);
    });
  }, [socket]);

PS。后端服务器仅向前端发回一次。 谢谢你的每一个回复:D

完整代码

import React from "react";
import { useEffect } from "react";
import { useState } from "react";

function Chat(props) {
  const { socket, username, room } = props;
  const [input, setInput] = useState("");
  const [msg, setMsg] = useState([]);

  // send msg to server
  const send_msg = (e) => {
    if (input !== "") {
      socket.emit("send_msg", {
        room: room,
        author: username,
        message: input,
      });
    }
  };

  // listen to boardcast msg
  useEffect(() => {
    socket.on("broadcast_msg", (data) => {
      setMsg((list) => [...list, data]);
    });
  }, [socket]);

  return (
    <div className="chat">
      <div className="chat-header"></div>
      <div className="chat-body">
        {msg.map((data) => {
          return (
            <>
              <h1>{data.author}</h1>
              <h1>{data.room}</h1>
              <h1>{data.message}</h1>
            </>
          );
        })}
      </div>
      <div className="chat-footer">
        <input
          type="text"
          placeholder="Enter the message..."
          onChange={(e) => {
            setInput(e.target.value);
          }}
        />
        <button onClick={send_msg}>Send</button>
      </div>
    </div>
  );
}

export default Chat;
useEffect(() => {
    const eventListener = (data) => {
        setMsg((list) => [...list, data]);
    };
    socket.on("broadcast_msg", eventListener);

    return () => socket.off("broadcast_msg", listener);
  }, [socket]);

与听众一起做。 运行 使用 Effect 并在再次触发时清除侦听器,这应该可以解决问题。 或 运行 挂载时仅一次。

 useEffect(() => {
    socket.on("broadcast_msg", (data) => {
      setMsg((list) => [...list, data]);
    });
  }, []);