选择适合与Firestore的onsnapshot一起使用的React Hook
P粉555682718
P粉555682718 2023-08-24 13:48:51
[JavaScript讨论组]

我在我的React Native应用程序中使用了很多Firestore快照。我还使用了React hooks。代码看起来像这样:

useEffect(() => {
    someFirestoreAPICall().onSnapshot(snapshot => {

        // 当组件初始化加载时,将所有加载的数据添加到状态中。
        // 当Firestore上的数据发生变化时,我们在此回调中接收到更新,
        // 然后根据当前状态更新UI

    });;
}, []);

起初,我认为useState是存储和更新UI的最佳hook。然而,根据我的useEffect hook的设置,它带有一个空的依赖数组,当快照回调被触发并且我尝试使用新更改修改当前状态时,当前状态是未定义的。我认为这是由于闭包引起的。我能够通过使用useRefforceUpdate()来解决这个问题,代码如下:

const dataRef = useRef(initialData);

const [, updateState] = React.useState();
const forceUpdate = useCallback(() => updateState({}), []);

useEffect(() => {
    someFirestoreAPICall().onSnapshot(snapshot => {

       // 如果快照数据被添加
       dataRef.current.push(newData)
       forceUpdate()

       // 如果快照数据被更新
       dataRef.current.find(e => some condition) = updatedData
       forceUpdate()

    });;
}, []);

return(
// 使用dataRef.current的JSX
)

我的问题是,我是否正确地使用了useRef以及与useState不同的forceUpdate?我觉得在整个应用程序中更新useRef hook并调用forceUpdate()并不正确。当尝试使用useState时,我尝试将状态变量添加到依赖数组中,但结果导致无限循环。我只想要初始化快照函数一次,并且希望组件中的有状态数据随着后端的变化而随时间更新(在onSnapshot回调中触发)。

P粉555682718
P粉555682718

全部回复(2)
P粉806834059

如果你结合使用 useEffect 和 useState,会更好。useEffect 负责设置和解除监听器,useState 只需要负责你需要的数据。

const [data, setData] = useState([]);

useEffect(() => { 
       const unsubscribe = someFirestoreAPICall().onSnapshot(snap => {
         const data = snap.docs.map(doc => doc.data())
         this.setData(data)
       });

       //记得在卸载组件时取消实时监听器,否则会造成内存泄漏
       return () => unsubscribe()
}, []);

然后你可以在你的应用中直接引用 useState 钩子中的 "data"。

P粉165522886

A simple useEffect worked for me, i don't need to create a helper function or anything of sorts,

useEffect(() => {
        const colRef = collection(db, "data")
        //real time update
        onSnapshot(colRef, (snapshot) => {
            snapshot.docs.forEach((doc) => {
                setTestData((prev) => [...prev, doc.data()])
                // console.log("onsnapshot", doc.data());
            })
        })
    }, [])

一个简单的useEffect对我很有用,我不需要创建任何帮助函数或类似的东西,

useEffect(() => {
        const colRef = collection(db, "data")
        //实时更新
        onSnapshot(colRef, (snapshot) => {
            snapshot.docs.forEach((doc) => {
                setTestData((prev) => [...prev, doc.data()])
                // console.log("onsnapshot", doc.data());
            })
        })
    }, [])
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号