Prevent possibly undefined user with useQuery
I have a hook
useUser
that looks basically like this
Lets imagine that its used in a Layout
so when the user is loading the whole app is just a loading spinner.
Now I want to get the user inside a component nested in Layout
Using useUser
hook makes no sense here because its return is always User | undefined
as typescript doesn't know the user is loaded somewhere higher. How do I solve this problem? Checking
Doesn't seem good because the user is always here if the component rendered.70 Replies
Also prop drilling user is not what I want to do here. Maybe I should?
returning null or whatever if the user isn't loaded is fine imo
you're using react-query or trpc right?
react-query
even if you get the user further up in the in the component tree, the query might become stale or invalidated
so you don't know for sure that it exists in the component
But if the query is stale or invalidated it is still there isnt it?
its possible to reach a state in react-query where the data is gone
you could stick the user into context or zustand or something, tkdodo wrote some stuff about this recently
I was thinking about something likes this
And this hook would be used inside a
Layout
.
So when I used this hook somewhere where the user wasnt fetched before i would immediately see an error
This way I wouldnt have to do this check
Idk if its a good idea thoUnknown User•2y ago
Message Not Public
Sign In & Join Server To View
😎
ty
TypeScript | TanStack Query Docs
React Query is now written in TypeScript to make sure the library and your projects are type-safe!
Things to keep in mind:
I dont want to prop drill it as you do it here
I would like to use my
useUser
hook further in the component tree but not check everytime if its loaded because It will be always there in for example <User />
I described it above the threadUnknown User•2y ago
Message Not Public
Sign In & Join Server To View
@Moro Why do you think 2nd custom hook that always returns user otherwise throws breaks typesafety?
I can't think of a case when it would break something in production. Such a mistake would be easily noticeable during development
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
sure thanks
you are kind of reinventing the wheel
the purpose of react query is to handle these issues for you
and act as a global state for your application
while handling all the complications that synchronizing with server state inherently has
and providing a clean, easy to use API for you and your components
this is not possible
you have to check
if you do it like this, then it's probably better to put it in a context
nah
ur just misunderstanding us @robotkutya
oh, okay then
so if for some reason you don't want to just use react query, and check for
isSuccess
as recommentded by the docs (and common sense)
and want a custom hook the way you described
you might as well just put it into a context
so the error handling is cleaner
you won't be able to call the custom hook, unless it is inside the provider, that has the user as definedUnknown User•2y ago
Message Not Public
Sign In & Join Server To View
which is why it would make sense to put it into a context if you don't want the prop drilling, so the entire component tree after the initial loading state has access to a not undefined user object
having it in a context helps with components that rely on the user not being used outside the context
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
in react query's context
but OP doesn't like the fact that the return type of that is
foo | undefined
and also doesn't like the recommended way of narrowing the type via checking for {isSuccess} = useFoo()
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
so, what you can do, is create a context, that needs a defined user
<UserContext />
and then handle the loading before setting up the context
which is what happens anywaysUnknown User•2y ago
Message Not Public
Sign In & Join Server To View
hold my tea... brb...
there you go
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
I think it makes sense to make it explicit that the component requires a user that is defined
better error handling
but, I wouldn't do either of these... since react query already does this well... and you can just check for {isSuccess}
on the page load / layout / data fetching level
and just pass down the prop to the presentational / pure components
*parts of the user they need
not the whole thing
But the error handling is the same here
Both ways u get an error
when you try to access user when its not fetched
not entirely
if you use a component that has the custom hook in it
with the provider - context version
you get immediate feedback in your editor
red squigly lines
🤔
prevents you from breaking the app, when you accidentally pull in the component outside the loading state
how
Editor doesnt recognize if the context is used within provider
The error would be noticeable in the runtime
maybe I'm trippin'
let me check
Thats exactly what u did above
If context is undefined - its used outside a provider
Then the error is thrown
and u will see this error in runtime
Not in IDE
yeah but doesn't this throw a TS error?
How would ts know if u r trying to access context inside/outside a provider
Check it ;D
hold on
btw I would check that differently as you would probably initialize context as
null
rather than undefined
meh... I totally thought there is some TS type narrowing magic in the background and the IDE would pick it up
okay, then the only advantage is (btw, it's a BAD solution I think)
that it's more explicit that you need the user object defined
if you pull in a component somewhere down the tree, and you are accidentally outside of the branch that handles the loading state
anyway, I kind of just pulled that one out of my *ss, I still think checking for
{isSuccess}
coming from react-query
is the way to go, and passing down the tree
oh yeah, one more thing... doesnt putting it inside a context help with error boundaries?
so if it's in a context, your app doesn't crash, if it's just a custom hook and you throw an error, the whole app crashes...?I think that in both ways app crashes
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
I mean, it's your code and you can do whatever you want...
But if you want to go full Ron Swanson "I know more than you" on TypeScript
Might as well just start using the exclamation mark
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
yes, you are
if you follow to what OP wants to do
(no passing down as prop, etc)
react-query has the type narrowing built in, safely
and it is tied to the
{isSuccess}
check
it's not an error when the user object is undefined
it's the reality of having it in the cache or not having it in the cacheUnknown User•2y ago
Message Not Public
Sign In & Join Server To View
okay sure, if you consider that an improvement...
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
yeah, and you have 2 options
1 option makes sure at compile time that you don't accidentally go into a branch where the user is not available
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
option 2 can only tell at runtime
i'm going to chose option 1
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
it's a pretty bad pattern
but I guess we reached a point where we agree to disagree
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
yes, of course, but OP vehemently opposed passing the defined user object down as a prop
or putting it in a context
or a global state
(after the check)
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
not really, if your components are more than 2 levels deep, you probably have some issues you should resolve
plus, it's better to only pass the parts that you need
so if a component only needs let's say 2 attributes off of user, don't pass the whole god damn thing down as a prop
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
2 levels of hierarchy
A --> B --> C
A passes it down to B passes it down to C
I'm in general fine with prop drilling up until this
if there is C --> D
then I reach for a solution (like jotai or context, global state)
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
yaaay
then we agree
😄
okay let's go find something to argue about
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
oh man, go check it out
react-query solved the whole data fetching game
it's over, done, finito
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
I had such a bad experience with apollo in general
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
have you tried this?
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
glhf 🖖