Choosing a React Hook suitable for use with Firestore's onsnapshot
P粉555682718
2023-08-24 13:48:51
<p>I use Firestore snapshots a lot in my React Native app. I also used React hooks. The code looks like this: </p>
<pre class="brush:php;toolbar:false;">useEffect(() => {
someFirestoreAPICall().onSnapshot(snapshot => {
// When the component initially loads, add all loaded data to the state.
// When the data on Firestore changes, we receive updates in this callback,
// Then update the UI based on the current state
});;
}, []);</pre>
<p>At first, I thought <code>useState</code> was the best hook to store and update the UI. However, according to the settings of my <code>useEffect</code> hook, which comes with an empty dependency array, when the snapshot callback is fired and I try to modify the current state with new changes, the current state is undefined. I think this is due to closures. I was able to solve this problem by using <code>useRef</code> and <code>forceUpdate()</code> with the following code: </p>
<pre class="brush:php;toolbar:false;">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 the snapshot data is updated
dataRef.current.find(e => some condition) = updatedData
forceUpdate()
});;
}, []);
return(
// JSX using dataRef.current
)</pre>
<p>My question is, am I using <code>useRef</code> correctly as well as <code>forceUpdate</code> which is different from <code>useState</code>? I feel like updating the <code>useRef</code> hook and calling <code>forceUpdate()</code> throughout the application is not correct. When trying to use <code>useState</code>, I tried adding the state variable to the dependency array, but it resulted in an infinite loop. I only want to initialize the snapshot function once, and want the stateful data in the component to update over time as the backend changes (triggered in the onSnapshot callback). </p>
It will be better if you combine useEffect and useState. useEffect is responsible for setting and disabling the listener, and useState is only responsible for the data you need.
You can then directly reference "data" in the useState hook in your application.
A simple useEffect worked for me, i don't need to create a helper function or anything of sorts,
A simple useEffect works for me, I don't need to create any helper functions or anything like that,