如何使用条件更新 useState-hook?

How to update a useState-hook with a condition in react?

我在 firebase 中使用反应挂钩(useEffect 和 useState)。

我有一个用户集合,可以毫无问题地从 firebase 获取这些用户。简化的代码如下所示:

const [users, setUsers] = useState([]);

  useEffect(() => {
    const unsubscribe = database.collection("users").onSnapshot((snapshot) => {
      snapshot.forEach((doc) => {
        const currentUser = {
          id: doc.id,
          ...doc.data(),
        };

        setUsers((oldUsers) => [...oldUsers, currentUser]);
      });
    });

    return () => {
      unsubscribe();
    };
  }, []);

到目前为止,还不错。

如果我现在更改用户的一些属性,firebase 会触发并触发 useEffect-hook(这就是我想要的)。

这里的问题: 通过这次触发我的用户数组 (useState) 得到更新并再次推送相同的用户。

我现在想要达到的是这样的:

我只想在我的用户数组中每个用户一次。所以只有新用户应该被添加到这个数组中。我想我需要在 setUsers 方法中进行条件检查。

我想到了这样的事情:

  setUsers(
          (oldUsers) =>
          {
            if (oldUsers.indexOf(currentUser) === -1) {
              oldUsers.push(currentUser);
            }
            
            // HERE I'M NOT SURE WHAT TO DO
            // how can I set my users to the updated oldUsers?
            // I made some first steps with those approaches...
            1) return oldUsers; 
            2) setUsers(oldUsers);
            3) [...oldUsers]
          }
        );

如代码注释中所述:我如何 update/set 我的用户升级到较新的版本(以防插入新用户)或让用户保持原样(无需再次添加) )?

感谢您的建议!

避免间接改变状态(使用 Array.push 或任何其他方式),它是不一致的。相反 return 如果没有变化则为原始状态,如果有变化则为新对象。例如:

setUsers(oldUsers => {
  if (oldUsers.find(user => user.id === currentUser.id)) 
    return oldUsers;
  return [...oldUsers, currentUser];
});

在这种特殊情况下,如果没有变化,您可能希望完全避免调用 setUsers,因为状态本身可用(并且您可以之前检查用户是否存在)。


作为旁注,indexOf 检查在这种情况下不起作用,因为您创建了一个新对象(从您在快照中获得的数据)。这就是为什么它 predicate-based 在我的示例中找到。