react-native-firebase含array-contains的useEffect查询导致组件持续刷新
问题1:array-contains 用法错误
Firestore 的 array-contains 操作符用于匹配数组字段中是否包含单个指定值,你最初的写法传入['60ddd70c7a3a1e8e62d14dac']数组作为匹配值,相当于查询usersIds字段中是否存在一个值为该数组本身,自然无法匹配到数据,正确写法就是直接传入字符串ID:
.where('usersIds', 'array-contains', '60ddd70c7a3a1e8e62d14dac')
问题2:组件无限刷新、查询重复执行、状态被清空
这三个问题都是useEffect使用不当导致的:
- 你没有给
useEffect指定依赖数组,导致每次组件渲染都会重新执行useEffect逻辑,反复注册、卸载监听器,触发重复查询 - 你对
querySnapshot做了非空判断,为空时返回null赋值给threads状态,实际上onSnapshot回调返回的querySnapshot永远不会为null,无匹配数据时docs字段为空数组,你的错误判断导致状态被意外清空 - 你使用了
where+orderBy的组合查询,需要提前在Firebase控制台创建对应的复合索引,否则查询会直接报错,这也是你说加了依赖数组后查询不生效的常见原因
修正后完整代码
import { useState, useEffect } from 'react' import firestore from '@react-native-firebase/firestore' // 固定的用户ID可以提到组件外,避免触发重渲染 const CURRENT_USER_ID = '60ddd70c7a3a1e8e62d14dac' function ThreadList() { const [threads, setThreads] = useState([]) const [loading, setLoading] = useState(true) useEffect(() => { const unsubscribe = firestore() .collection('THREADS') .where('usersIds', 'array-contains', CURRENT_USER_ID) .orderBy('latestMessage.createdAt', 'desc') .onSnapshot( querySnapshot => { // 直接处理文档列表,无数据时返回空数组即可 const queriedThreads = querySnapshot.docs.map(doc => ({ ...doc.data(), id: doc.id })) setThreads(queriedThreads) if (loading) setLoading(false) }, error => { // 错误捕获,缺索引时会在这里打印报错,点击报错里的提示即可自动创建对应索引 console.error('线程查询失败:', error) if (loading) setLoading(false) } ) // 组件卸载时取消监听器 return () => unsubscribe() // 依赖数组只放动态变化的变量,如果用户ID是动态传入的,把对应变量加到这里即可 }, [loading]) // 组件渲染逻辑 }
额外注意事项
如果运行后控制台报索引缺失错误,按照错误提示在Firebase控制台创建对应索引,等待1-2分钟索引创建完成后查询即可正常返回结果。
内容的提问来源于stack exchange,提问作者XplosiVe06
相关产品推荐
相关产品推荐

