javascript - 如何使用反应条件更新useState-hook?
问题描述
我正在使用带有 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]
}
);
正如代码中的评论所述:如何将我的用户更新/设置为较新的版本(以防插入新用户)或让用户保持原样(无需再次添加)?
我很感谢任何建议!
解决方案
避免间接地(使用Array.push
或任何其他方式)改变状态,这是不一致的。如果没有变化,则返回原始状态,如果有,则返回一个新对象。例如:
setUsers(oldUsers => {
if (oldUsers.find(user => user.id === currentUser.id))
return oldUsers;
return [...oldUsers, currentUser];
});
setUsers
在这种特殊情况下,如果没有更改,您可能希望完全避免调用,因为状态本身是可用的(并且您可以在之前检查用户的存在)。
作为旁注,indexOf
在这种情况下检查将不起作用,因为您创建了一个新对象(根据您在快照中获得的数据)。这就是为什么在我的示例中它是基于谓词的查找。
推荐阅读
- typo3 - TYPO3 - 翻译不显示,总是默认语言
- javascript - jquery加载函数不调用spring boot控制器来替换thymeleaf模板片段
- angular - 如何像我们在angular js中但在angular 5中一样包含html文件?
- javascript - 如何检查所有输入是否已正确填写,然后将其更改为绿色
- javascript - FullCalendar 尝试从 URL 而不是数组中获取事件
- javascript - Vuejs - 使用模板将父组件道具传递给子元素
- r - 在两个数据框中查找最接近的坐标匹配
- javascript - React - 加载外部脚本给我错误:无法在“文档”上执行“写入”
- postgresql - 如何授予用户对 Postgres 中所有新表的权限?
- java - 满足一定条件后自动在 JAVA swing 中配置框架