首頁  >  問答  >  主體

選擇適合與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 天前465

全部回覆(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
  • 取消回覆