React JS中Firebase Firestore数组内元素更新问题求助
Firestore数组元素更新问题解决思路
问题背景
需要更新Firestore数组中的字符串,官方文档没有直接更新数组元素的方法,仅提供arrayUnion(添加元素)和arrayRemove(移除元素)两个API。尝试先调用arrayUnion添加新内容、再调用arrayRemove移除旧内容来实现更新,但同时使用两个方法时只有arrayRemove生效,新元素未添加。
问题代码
const updateField = async (e, id, obj) => { const taskDoc = doc(db, "Task", id); if (e.target.id == "updateTodos") { const updatedTask = { Todos: arrayUnion(updatedTodo), Todos: arrayRemove(obj), }; await updateDoc(taskDoc, updatedTask); setUpdateHadHappened(updateHasHappened + 1); exitEditMode(); }
尝试过的无效写法:
Todos: arrayUnion(updatedTodo), arrayRemove(obj),
Todos: arrayUnion(updatedTodo); arrayRemove(obj);
问题原因
JavaScript对象不允许存在重复属性,后面的属性会直接覆盖前面的。你在updatedTask里给Todos赋值了两次,最终只有最后一次的arrayRemove(obj)生效,arrayUnion(updatedTodo)被完全覆盖,所以新元素无法添加。
解决方案
Firestore支持在原子性更新中对同一个字段执行多个数组操作,但需要改用数组形式的更新参数(而非对象字面量),这样可以避免属性覆盖问题,同时保证两个操作在同一次更新中完成。
修正后的代码:
const updateField = async (e, id, obj) => { const taskDoc = doc(db, "Task", id); if (e.target.id == "updateTodos") { // 用数组传递多个操作,每个操作是[字段名, FieldValue操作]的数组 await updateDoc(taskDoc, [ ["Todos", arrayRemove(obj)], ["Todos", arrayUnion(updatedTodo)] ]); setUpdateHadHappened(updateHasHappened + 1); exitEditMode(); } }
补充说明
如果不需要原子性,也可以分两次调用updateDoc(先移除旧元素,再添加新元素),但这种方式存在并发风险——如果中间有其他客户端修改数组,可能导致数据不一致,因此优先推荐原子性的数组参数写法。
内容的提问来源于stack exchange,提问作者Jonathan Ribak
相关产品推荐
相关产品推荐

