Firebase arrayUnion调用报错:传入自定义UserImpl对象无效
解决Firestore arrayUnion传入UserImpl对象报错问题
问题原因
报错明确指出你传入arrayUnion()的是Firebase Auth的UserImpl自定义对象,而非普通JS对象。你认为user是普通对象,但实际上这个user应该是Firebase Auth返回的用户实例(比如getAuth().currentUser),这类对象包含Firestore无法序列化的内部方法和属性,因此无法直接存入数组。
而第一个updateDoc能用chat成功执行,大概率是因为chat是从Firestore读取的纯JSON对象,没有自定义类的属性。
解决方案
不要直接传入UserImpl对象,而是提取你需要的用户字段,创建纯JavaScript对象后再存入Firestore,两种可选方式:
- 手动提取必要字段(推荐,避免冗余数据):只保留业务需要的属性,比如
uid、displayName、email等。 - 序列化转普通对象:用
JSON.parse(JSON.stringify(user))快速转换,但会丢失无法序列化的属性(比如方法),适合需要大部分属性的场景。
修改后的代码示例
方案1:手动提取字段
const handleSelect = async(chat) =>{ const docRef = doc(db, 'users', user?.uid) const docSnap = await getDoc(docRef) const addRef = doc(db, 'userChats', user?.uid) await updateDoc(addRef, { userChats: arrayUnion(chat) }) // 提取user的必要字段,创建纯JS对象 const userData = { uid: user.uid, displayName: user.displayName, email: user.email // 按需添加其他你需要的字段 } const addRecieverRef = doc(db, 'userChats', chat?.uid) await updateDoc(addRecieverRef, { userChats: arrayUnion(userData) // 传入纯对象 }) console.log(chat.uid) const concatUID = user.uid > chat.uid ? user.uid + chat.uid : chat.uid + user.uid; if(!docSnap.exists() && user.uid!=chat.uid){ await setDoc(doc(db, 'messages', concatUID), { messages: [], }) } else{ dispatch({type: 'CHANGE_USER', payload: chat}) console.log(chat) } }
方案2:序列化转换
const handleSelect = async(chat) =>{ const docRef = doc(db, 'users', user?.uid) const docSnap = await getDoc(docRef) const addRef = doc(db, 'userChats', user?.uid) await updateDoc(addRef, { userChats: arrayUnion(chat) }) // 将UserImpl对象转为普通JS对象 const userData = JSON.parse(JSON.stringify(user)) const addRecieverRef = doc(db, 'userChats', chat?.uid) await updateDoc(addRecieverRef, { userChats: arrayUnion(userData) }) console.log(chat.uid) const concatUID = user.uid > chat.uid ? user.uid + chat.uid : chat.uid + user.uid; if(!docSnap.exists() && user.uid!=chat.uid){ await setDoc(doc(db, 'messages', concatUID), { messages: [], }) } else{ dispatch({type: 'CHANGE_USER', payload: chat}) console.log(chat) } }
验证点
- 用
console.log(userData)确认是纯JS对象,没有UserImpl的内部属性和方法 - 确保存入的字段是后续业务需要的,避免冗余数据
内容的提问来源于stack exchange,提问作者Het Patel
相关产品推荐
相关产品推荐

