Last active
April 22, 2020 00:14
-
-
Save gragland/6e4cd47df96efbb7f463287acc96cd94 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Usage | |
export function useUser(uid) { | |
return useQuery(uid && firestore.collection("users").doc(uid)); | |
} | |
// Custom useQuery hook for Firestore | |
function useQuery(query) { | |
const [queryState, setQueryState] = useState({ | |
status: "loading", | |
data: undefined, | |
error: null, | |
}); | |
// Gives us previous query object if query is the same | |
// ensuring we don't unsubscribe and resubscribe below. | |
const queryCached = useQueryCache(query); | |
useEffect(() => { | |
// Skip if falsy value, as that allows us to wait on needed | |
// needed data before constructing query and passing it into useQuery. | |
if (queryCached) { | |
return queryCached.onSnapshot( | |
(snapshot) => { | |
// Get data for collection or individual doc | |
const data = snapshot.docs | |
? snapshot.docs.map((doc) => { | |
// Return array of docs and merge in doc id | |
return { id: doc.id, ...doc.data() }; | |
}) | |
: snapshot.exists === true | |
? { id: snapshot.id, ...snapshot.data() } | |
: null; | |
setQueryState({ | |
status: "success", | |
data: data, | |
error: null, | |
}); | |
}, | |
(error) => { | |
setQueryState((state) => ({ | |
status: "error", | |
data: state.data, | |
error: error, | |
})); | |
} | |
); | |
} | |
}, [queryCached]); | |
return queryState; | |
} | |
function useQueryCache(query) { | |
// Ref for storing previous query object | |
const previousRef = useRef(); | |
const previous = previousRef.current; | |
// Determine if query object is equal to previous | |
const isEqual = | |
(!previous && !query) || (previous && query && previous.isEqual(query)); | |
// If not equal update previous to query (for next render) | |
// and then return new query below. | |
useEffect(() => { | |
if (!isEqual) { | |
previousRef.current = query; | |
} | |
}); | |
return isEqual ? previous : query; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment