CSFrequency/react-firebase-hooks

How do you reading user document when logged in and skip if not

saillcemail opened this issue · 5 comments

Hi guys,
This might be a simple on and I am not professional in ReactJS.
Q: In my home page I am reading, the user document for the logged in user. If the user is logged in I will display some information from it. If not, that section is hidden.
const [user, loading, error] = useAuthState(auth); const [value, docLoading, docError] = useDocumentOnce(firestore.doc('/users/' + user.uid), { snapshotListenOptions: { includeMetadataChanges: true }, });
It throws an error for not logged in case and if I check the user value, then throws an error: "React Hook "useDocumentOnce" is called conditionally. React Hooks must be called in the exact same order in every component render"
I can create a component/separate page might be a solution.
Is there a better way to do this?

Hi, I think you can make use of the fact that you can pass a null value as document reference here. You might want to try the following:

const [user, loading, error] = useAuthState(auth);
const [value, docLoading, docError] = useDocumentOnce(user ? firestore.doc('/users/' + user.uid) : null, {
    snapshotListenOptions: { includeMetadataChanges: true },
});

Perhaps it would also work with:

const [user, loading, error] = useAuthState(auth);
const [value, docLoading, docError] = useDocumentOnce(user && firestore.doc('/users/' + user.uid) , {
    snapshotListenOptions: { includeMetadataChanges: true },
});

Thank you, @mauriceackel. That worked.

I wanted to bring this issue back to life again to suggest a new feature...

So conditional loading is something that would come in hand, like saillcemail mentioned, in case a user is not logged in, or a specific data is not loaded yet... Your approach works, but feels kinda like a hack, having these ternaries in the document reference...

I've worked with React Query in the past, and they have a pretty handy option to not do an API call in case a condition is not met, it's an option called enabled.

I think it would be an easier way to set it up, if we had the same option for the document and collection hooks, something like:

const [user, loading, error] = useAuthState(auth);
const [value, docLoading, docError] = useDocumentOnce(firestore.doc('/users/' + user.uid) , {
   enabled: !!user
});

What do you think? If you're ok with this, I'd be happy to open a PR with an implementation, add some tests and update the docs in case you don't have time for it.

Hey @mauriciosoares I just quickly scanned over your suggestion and I just wanted to mention that with this solution there would potentially still be typescript issues. Although they might be solved by simply using the ‘?‘ operator, I still think that my initial approach is valid.

If you don't like using a ternary in the document reference, simply use a useMemo hook to achieve the same functionality in a perhaps "cleaner" way...

Cheers, Maurice

@mauriciosoares, as @mauriceackel says, the example you give wouldn't work when the user is not defined as user.uid would throw an error so you would have to protect against this with a ternary, or similar, anyway, so in that instance you'd just be moving the same logic elsewhere in your code.

Whilst the React Query approach is another way of doing things, I'm loathe to introduce additional complexity to the codebase and feel that the use of a null / undefined document reference is a simpler take on the same thing.