React-为什么多次调用useEffect(即使有条件)?

时间:2019-12-30 18:34:22

标签: javascript arrays reactjs socket.io

Example of 4 messages

我使用带React钩子的简单聊天应用程序工作。 在第二个useEffect 中,我需要将新消息添加到其余消息中,以便能够在聊天中显示所有消息。现在,仅在从数组的长度中将useEffect称为x2之后,才可以附加消息。例如:在第四条消息中,UseEffect将在数组完成之前执行8次。

通知:在useEffect中,我两次设置了AllMessages,但是只有一个正在执行,这取决于它是否是发件人的收件者(所以我不认为这是问题所在)


function Chat() {
  const [message, setMessage] = useState("");
  const [userName] = useState(
    JSON.parse(atob(localStorage.getItem("token").split(".")[1])).name
  );
  const [userTyping, setUserTyping] = useState(null);
  const [allMessages, setAllMessages] = useState([]);

  useEffect(() => {
    socket.emit("join", userName);
    socket.on("chat-message", data => {
      toast(`Hello ${data}`);
    });
    socket.on("user-joined", data => {
      toast(`${data} joined the chat`);
    });
  }, [userName]);

  useEffect(() => {                             // the problem is here
    function handleAllMessages(data) {
      setAllMessages([...allMessages, data]);
      console.log(allMessages);
    }
    socket.on("broadcast-message", data => {
      handleAllMessages(data);
    });
    socket.on("my-message", data => {
      data["userName"] = "You";
      handleAllMessages(data);
    });
  }, [allMessages]);

  useEffect(() => {
    socket.on("who-typing", data => {
      setUserTyping(data);
      setTimeout(() => {
        setUserTyping(null);
      }, 2500);
    });
  }, [userTyping]);

  useEffect(() => {
    socket.on("user-disconnected", data => {
      toast(`${data} left the chat`);
    });
  }, []);

  function handleChat(e) {
    e.preventDefault();
    if (message.trim() === "") return toast.warn("not valid message");
    socket.emit("user-message", message, userName);
    setMessage("");
  }

  function handleChange(e) {
    setMessage(e.target.value);
    socket.emit("typing", userName);
  }

  return (...

2 个答案:

答案 0 :(得分:0)

第二个useEffect会被执行多次(实际上我想无限地这样做)的原因是因为您告诉它每次allMessages更改都会执行一次,因为它在数组中- useEffect的第二个参数。

传递带有allMessages的数组将导致useEffect每次allMessages更改时都重新运行,这实际上是您在useEffect内所做的操作您正在调用handleAllMessages函数。

Read about this.

答案 1 :(得分:0)

在钩子中正确设置setAllMessages的方法(在这种情况下)是像这样传递oldArray ...

WebClient client = WebClient.create("www.google.com");
ObjectMapper mapper = new ObjectMapper();

client.get()
    .retrieve()
    .bodyToMono(String.class)
    .map(rawBody -> {
        try {
            return mapper.readValue(rawBody, Response.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Cannot deserialize string: " + rawBody);
        }
    });

在使用效果内,将空数组作为第二个参数传递,而不是setAllMessages(allMessages => [...allMessages, data]);

此问题已解决