我正在使用React with Firebase从firestore获取数据并显示给用户。在useEffect钩子中,我获取数据并将其添加到json对象数组中。然而,当向数组添加新元素时,前一个元素会被删除。以下是相关代码部分。
const [items, setItems] = useState([]);
const [isLoading, setLoading] = useState(true);
const { currentUser } = useAuth();
function addItemToList(i) {
const updatedList = [
...items,
{
data: i.data(),
ref: i.ref
}
]
return updatedList;
}
useEffect(() => {
firestore.collection('items').where('uid', '==', currentUser.uid).get().then((itemSnapshot) => {
itemSnapshot.forEach((doc) => {
setItems(addItemToList(doc));
})
})
setLoading(false);
}, []);
我还尝试过更新useEffect
钩子中的items
列表,但它产生了相同的bug。
5条答案
按热度按时间7xllpg7q1#
让我花点时间解释一下这里发生的事情。
你必须把react组件想象成一个“快照”,其中快照是渲染的结果。每个快照指向useState创建的一个状态,并且只指向那个状态。这意味着什么?
组件第一次呈现(第一个快照)时,useState返回的items变量指向一个空数组,并且只要该快照处于活动状态,它就会指向该数组。
那么,让我们来看看useEffect调用的函数
您在firebase查询结果中为每个元素调用一次项的set函数,并且每次调用都设置一个值,该值是调用addItemToList的结果
这里的要点是你总是在解构...项目,它总是组件快照所指向的项目变量,并且它不会被更新,直到组件重新排序。
所以,基本上你总是做updatedList = [...[],{...} ],因为项目必须等待更新他的值。
@Viet已经回复了好东西,我觉得这是最好的选择
将所述查询的结果Map到数组,并且用所述Map的结果作为参数更新所述数组。
9rygscc12#
您需要将“addItemToList”添加到useEffect钩子的依赖项中。
因为您还没有这样做,所以效果引用了该函数的旧版本,该函数引用了旧版本的items数组。
uinbv5nw3#
您只需像这样使用
itemSnapshot.map
:yqkkidmi4#
也许您应该尝试将其Map为列表并更新一次状态,而不是为每个值运行它
qcbq4gxm5#
**您使用spread运算符的方式错误!**这种方式不会更新数组。
您可以使用es6spread来连接多个数组,如下所示:
要了解更多信息:Using es6 spread to concat multiple arrays