Closed tettoffensive closed 4 years ago
You can also use null
as key of your second useSWR call.
const { data: user } = useSWR('/api/user');
const { data: block, error } = useSWR(user?.id ? `/api/users/${mUser.id}/${(blocks as string[]).join('/')}` : null);
I see so if user.id
evaluates to null
the call will not be made, but if user.id
evaluates to undefined
it will.
@sergiodxa Is there a reasoning for this?
I think the docs should be updated
SWR will not fire the request if:
key
is a function and it throwskey
is falsy (null
, undefined
, ...)I think the docs is clear about that.
Note that mUser.id
will always throw if mUser
is null
OR undefined
.
@shuding
The comment from the "Dependent Fetching" on https://swr.now.sh/#dependent-fetching only mentions If the function throws
not or returns falsy
. So I didn't find that clear. More importantly, I followed this example, and found that the second useSWR did get called when user = {}
(AND therefore, user.id === undefined
)
SWR allows you to fetch data that depends on other data. It ensures the maximum possible parallelism (avoiding waterfalls), as well as serial fetching when a piece of dynamic data is required for the next data fetch to happen.
import useSWR from 'swr'
function MyProjects() {
const { data: user } = useSWR('/api/user')
const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id))
// When passing a function, SWR will use the
// return value as `key`. If the function throws,
// SWR will know that some dependencies are not
// ready. In this case it is `user`.
if (!projects) return 'loading...'
return 'You have ' + projects.length + ' projects'
}
@tettoffensive that's expected:
useSWR did get called when
user = {}
Because {}
doesn't throw, and it isn't falsy. It's expected to not pause. I think the example assumes the API will always return null
if user isn't found, instead of {}
. In fact I think most APIs do the same.
In your specific case, I would do this:
const { data: user } = useSWR('/api/user')
const { data: projects } = useSWR(() => {
if (!user.id) throw new Error('user not ready')
return '/api/projects?uid=' + user.id
})
Yes you are correct user is not falsy. I was originally assuming because user.id is undefined it would not fire. But this is not the case, therefore my workaround.
I was struggling with the following until I realized that it actually had to throw an error for the second call not to happen. My
/api/user
call returns some data even if the user id isn't available. So callinguser.id
doesn't throw an error, it just returns undefined.My solution was to make another user variable that is null if the user.id is null. Since
mUser
is now undefined,mUser.id
will throw an error.I'm wondering if there's already a better way to do this or a way in which I could have dependencies wait on data to be defined?