简体   繁体   English

Array.push 多次推送内容

[英]Array.push pushes the content multiple times

    useEffect(() => {
    socket.on("private message", ({ content, from }) => {
      console.log(content, from, "content & form");
      for (let i = 0; i < usersList.length; i++) {
        var user = usersList[i];
        if (user.userID === from) {
          console.log("user from");
          user.messages.push({
            content,
            fromSelf: false,
          });
          if (user !== selectedUser) {
            console.log("user to");
            user.hasNewMessages = true;
          }
          break;
        }
      }
    });
  }, [usersList, selectedUser]);

I am using socket to make private chat, but the thing is that user.messages.push, pushes the content multiple times because it is inside the for loop, here usersList is a list of all connected users, so if 3 users are connected, it will loop 3 times and then the messages will be pushed 3 times, How do I fix this so that it only pushes one time and not with relative to the number of users connected?我正在使用套接字进行私人聊天,但问题是 user.messages.push 多次推送内容,因为它在 for 循环内,这里 usersList 是所有连接用户的列表,所以如果连接了 3 个用户,它将循环 3 次,然后消息将被推送 3 次,我该如何解决这个问题,以便它只推送一次而不是相对于连接的用户数量?

selectedUser is the user that the loggedIn user wishes to initiate a conversation with selectedUser 是已登录用户希望与其发起对话的用户

NOTE : I need a solution except for maintaining a state and then changing it with first iteration and conditionally running the logic, Pls tell me other that this.注意:我需要一个解决方案,除了维护一个 state 然后通过第一次迭代更改它并有条件地运行逻辑,请告诉我其他的。

You are attaching new listeners each time the useEffect hook runs after usersList or selectedUser update.每次在usersListselectedUser更新后运行useEffect挂钩时,您都会附加新的侦听器。 Each time the effect callback runs a new listener is added, and each one runs the same "private message" event callback.每次效果回调运行时都会添加一个新的侦听器,并且每个侦听器都会运行相同的“私人消息”事件回调。 This is where the message content duplication is occurring.这是发生消息内容重复的地方。

I suspect you want only one listener.我怀疑你只想要一个听众。 Use an empty dependency array so the effect runs only once on component mount.使用一个空的依赖数组,这样效果只会在组件挂载时运行一次。

const messageHandler = ({ content, from }) => {
  console.log(content, from, "content & form");
  for (let i = 0; i < usersList.length; i++) {
    var user = usersList[i];
    if (user.userID === from) {
      console.log("user from");
      user.messages.push({
        content,
        fromSelf: false,
      });
      if (user !== selectedUser) {
        console.log("user to");
        user.hasNewMessages = true;
      }
      break;
    }
  }
}

useEffect(() => {
  socket.on("private message", messageHandler);
}, []);

You may see some lint warning about unspecified dependency on messageHandler , if necessary you can disable the linter for this as follows:您可能会看到一些关于对messageHandler的未指定依赖的 lint 警告,如有必要,您可以为此禁用 linter,如下所示:

useEffect(() => {
  socket.on("private message", messageHandler);
  // Run effect only on component mount
  // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

I think you need to keep the user.userID in your client and remove the for loop in the socket.on "private message" Event.我认为您需要将 user.userID 保留在客户端中,并删除 socket.on “私人消息”事件中的 for 循环。

Something like this:像这样的东西:

  // Global (Example values)
  const currentUser = 1;
  const usersList = [2, 3, 4, 5];

  useEffect(() => {
    socket.on("private message", ({ content, from }) => {
      console.log(content, from, "content & form");
        if (currentUser === from) { // The currentUser send a message to another user
          console.log("user from");
          user.hasNewMessages = true;
        } else if (user !== from) { // The currentUser receive a message from another user
            console.log("user to");
            user.messages.push({
                content,
                fromSelf: false,
            });
        }
    });
  }, [usersList, currentUser]);

This is what needed to be doing:这是需要做的:

if (shipments.length > 0) {
    shipments.map((item, key: number) => {
        if (item.lookup_scan === newobj.lookup_scan) {
           shipments[key] = newobj;
        }
    });
    shipments.push(newobj);
} else {
    shipments.push(newobj);
}

This is what I was doing:这就是我正在做的事情:

if (shipments.length > 0) {
    shipments.map((item, key: number) => {
        if (item.lookup_scan === newobj.lookup_scan) {
           shipments[key] = newobj;
        } else {
            shipments.push(newobj);
        }
    });
} else {
    shipments.push(newobj);
}
 const messageHandler = ({ content, from }: any) => {
    console.log(content, from, "content & form");
    var user;
    for (let i = 0; i < usersList.length; i++) {
      user = usersList[i];
    }
    if (user && user.userID === from) {
      console.log("user from");
      user.messages.push({
        content,
        fromSelf: false,
      });
      if (user !== selectedUser) {
        console.log("user to");
        user.hasNewMessages = true;
      }
    }
  };

  useEffect(() => {
    socket.on("private message", messageHandler);
  }, [usersList]);

This solved the bug, I had to move the Array.push out of the for loop.这解决了这个错误,我不得不将 Array.push 移出 for 循环。

Thanks everyone.感谢大家。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM