Hi there!
The recoil prefetch example in the docs seems to work, but only partially.
//prefetch
snapshot.getLoadable(userProfileQuery(id));
//trigger rerender
set(currentUserId, id);
The following works. The data is prefetched via the async selector userProfileQuery and set triggers a re-render.
However, if I read the state of the loadable via useRecoilLoadable, it remains "loading" even though the data is indeed fetched.
### Codesandbox example
Please see the following sandbox:

Truth be told, I'm not sure if I'm doing something wrong (looks good to me š ) or if this is an actual bug. Hoping to get clarification. Cheers!
If you have useRecoilValueLoadable passed a recoil selectorFamily whose dependence is local, you get this bug.
i.e
const value = useRecoilValueLoadable(userProfileQuery(currentUserId))
where currentUserId is an atom retrieved locally as follows:
const currentUserId = useRecoilValue(currentUserIdAtom)
const value = useRecoilValueLoadable(userProfileQuery(currentUserId))
Is this ideal? doesn't seem so. Moving userProfileQuery(currentUserId) to a selector of its own solves the problem i.e
const currentUserProfileQuery = selector({
key: "currentUserProfile",
get: ({get}) => get(userProfileQuery(get(currentUserId))
})
In component:
- const currentUserId = useRecoilValue(currentUserIdAtom)
- const value = useRecoilValueLoadable(userProfileQuery(currentUserId))
+ const value = useRecoilValueLoadable(currentUserProfileQuery)
See the solution implemented.
The component should be re-rendered still i.e invoking the selectorFamily userProfileQuery(currentUserId) where currentUserId is global atom state in the component should yield same results as pulling that out to a selector by itself i.e composing state entities within components should yield consistent results.
Thoughts?
The pre-fetch will only initiate the query to get it started; but since it doesn't wait until that completes, the subsequent re-render can still be issued and get a pending result. Getting the currentUserIdAtom in either a currentUserProfileQuery selector or in subsequent hook calls should produce the same result when the component using them is re-rendered. It's a problem, though, if the selector is actually resolving but then doesn't cause the subscribing component to re-render again after that resolves. We'll have to investigate this closer, thanks. (cc @davidmccabe )
I thought as much @drarmstr
I reckon this doesnāt only happen with āuseRecoilCallbackā - Iām happy to provide cases, but the crux remains the same I.e no re-render.
Thanks for taking a look. Happy to help in any other way.
We think a pending fix we have will resolve this, but still need to validate it.
This problem is fixed, the fix will be in the next release (0.0.11) which we expect to release on the 15th (we expected to release it last week and were wrong, and we could be wrong again, however).
The problem arises because the async selector is first read in the context of the snapshot provided to the callback. The selector implementation sees that the get function returns a promise, so it thens the promise to notify the store when the promise resolves. However, snapshots are internally implemented as their own store, and it's the snapshot that was being read from. So the snapshot is notified, but not the actual store.
You would hit the same problem if you had two RecoilRoots each with a component reading the same async selector.
With the fix we now keep track of each store that has asked for each pending selector.
Most helpful comment
We think a pending fix we have will resolve this, but still need to validate it.