web-dev-qa-db-ja.com

スナップショットのfirestoreで使用する反応フックはどれですか?

反応ネイティブアプリケーションで、多くのFirestoreスナップショットを使用しています。 Reactフックも使用しています。コードは次のようになります。

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

        // When the component initially loads, add all the loaded data to state.
        // When data changes on firestore, we receive that update here in this
        // callback and then update the UI based on current state

    });;
}, []);
_

最初は、useStateがUIの保存と更新に最適なフックであると最初に思いました。しかし、私のuseEffectフックが空の依存関係配列で設定されている方法に基づいて、スナップショットコールバックが更新されたデータで起動され、現在の状態を新しい変更で変更しようとすると、現在の状態は未定義です。これは閉鎖のためだと思います。私はuseRefforceUpdate()と一緒に使用してそれを回避することができます:

_const dataRef = useRef(initialData);

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

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

       // if snapshot data is added
       dataRef.current.Push(newData)
       forceUpdate()

       // if snapshot data is updated
       dataRef.current.find(e => some condition) = updatedData
       forceUpdate()

    });;
}, []);

return(
// JSX that uses dataRef.current directly
)
_

私の質問は、useRefの代わりにforceUpdateとともにuseStateを使用して別の方法でこれを正しく行うことですか?アプリ全体でuseRefフックを更新してforceUpdate()を呼び出す必要があるのは正しくないようです。 useStateを試してみると、依存変数の配列に状態変数を追加しようとしましたが、無限ループになってしまいました。スナップショット関数を1回だけ初期化し、コンポーネントのステートフルデータをバックエンド(onSnapshotコールバックで発生する)での変更に応じて時間の経過とともに更新したいだけです。

2
Kevin Quiring

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)
       });

//remember to unsubscribe from your realtime listener on umount or you will create a memory leak
       retun () => unsubscribe()
}, []);

次に、アプリのuseStateフックからdataを参照するだけです。

1
Josh Pittman

OnSnapshot()メソッドの内部で状態にアクセスできないことがわかりました(たとえば、console.log(state)の場合、空の値が返されます。

ヘルパー関数を作成することはうまくいきましたが、これがhack-yソリューションであるかどうかはわかりませんが、次のようなものです:

[state, setState] = useState([])

stateHelperFunction = () => {
//update state here
setState()
}

firestoreAPICall.onSnapshot(snapshot => {
stateHelperFunction(doc.data())
})
0
Tepinvic