首页  >  问答  >  正文

选择适合与Firestore的onsnapshot一起使用的React Hook

<p>我在我的React Native应用程序中使用了很多Firestore快照。我还使用了React hooks。代码看起来像这样:</p> <pre class="brush:php;toolbar:false;">useEffect(() => { someFirestoreAPICall().onSnapshot(snapshot => { // 当组件初始化加载时,将所有加载的数据添加到状态中。 // 当Firestore上的数据发生变化时,我们在此回调中接收到更新, // 然后根据当前状态更新UI });; }, []);</pre> <p>起初,我认为<code>useState</code>是存储和更新UI的最佳hook。然而,根据我的<code>useEffect</code> hook的设置,它带有一个空的依赖数组,当快照回调被触发并且我尝试使用新更改修改当前状态时,当前状态是未定义的。我认为这是由于闭包引起的。我能够通过使用<code>useRef</code>和<code>forceUpdate()</code>来解决这个问题,代码如下:</p> <pre class="brush:php;toolbar:false;">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 )</pre> <p>我的问题是,我是否正确地使用了<code>useRef</code>以及与<code>useState</code>不同的<code>forceUpdate</code>?我觉得在整个应用程序中更新<code>useRef</code> hook并调用<code>forceUpdate()</code>并不正确。当尝试使用<code>useState</code>时,我尝试将状态变量添加到依赖数组中,但结果导致无限循环。我只想要初始化快照函数一次,并且希望组件中的有状态数据随着后端的变化而随时间更新(在onSnapshot回调中触发)。</p>
P粉555682718P粉555682718398 天前466

全部回复(2)我来回复

  • P粉806834059

    P粉8068340592023-08-25 12:43:07

    如果你结合使用 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"。

    回复
    0
  • P粉165522886

    P粉1655228862023-08-25 12:37:51

    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());
                })
            })
        }, [])

    回复
    0
  • 取消回复