如何将Firebase onSnapshot快照返回结果存入数组且不使用state
问题根因
onSnapshot是异步监听回调,代码执行顺序和你预期的不一样:
- 进入
useEffect,初始化copyChats = [] - 注册
onSnapshot监听(回调函数不会立刻执行,需要等Firebase云端返回数据后才会触发) - 立刻执行
console.log(copyChats),这时候回调还未运行,所以打印的是空数组 - 等待一段时间后Firebase返回数据,回调触发,才会完成对
copyChats的赋值,你之前的赋值逻辑本身没有问题。
解决方案
方案1:把所有用到copyChats的逻辑都写到回调里
如果不需要在回调外部访问这个数组,直接把相关操作都放在onSnapshot回调内部即可:
useEffect(() => { let copyChats = []; const unsubscribe = db.collection('chats').onSnapshot(snapshot => { copyChats = snapshot.docs.map(doc => ({ id: doc.id, data: doc.data() })) // 所有和copyChats相关的操作都写在这里,比如打印、数据计算、渲染逻辑等 console.log(copyChats); }) return unsubscribe; }, [])
方案2:用useRef存储数组(适合需要在回调外部访问的场景)
useRef不属于状态语法,修改它的current值不会触发组件重渲染,完全符合你不使用state的要求:
import { useEffect, useRef } from 'react' // 组件内部逻辑 const copyChatsRef = useRef([]) useEffect(() => { const unsubscribe = db.collection('chats').onSnapshot(snapshot => { // 赋值给ref的current属性 copyChatsRef.current = snapshot.docs.map(doc => ({ id: doc.id, data: doc.data() })) console.log(copyChatsRef.current) }) return unsubscribe; }, []) // 任意其他位置要访问数组时,直接读copyChatsRef.current即可 const handleSomeEvent = () => { console.log('最新聊天列表:', copyChatsRef.current) }
内容的提问来源于stack exchange,提问作者Tercé Nicolas
相关产品推荐
相关产品推荐

