-
-
Notifications
You must be signed in to change notification settings - Fork 98
Description
Motivation
- fetch-as-render pattern results in over-fetching (non-stale data is fetched on every transition)
- centralize more handling - less in hooks = happier world
Current world
Currently final ‘stale’ logic exists in hooks
const { data, expiryStatus, expiresAt } = controller.getResponse(endpoint, ...args, state);
const forceFetch = expiryStatus === ExpiryStatus.Invalid
const maybePromise = useMemo(() => {
// null params mean don't do anything
if ((Date.now() <= expiresAt && !forceFetch) || !key) return;
return controller.fetch(endpoint, ...(args as readonly [...Parameters<E>]));
// we need to check against serialized params, since params can change frequently
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [expiresAt, controller, key, forceFetch, state.lastReset]);This isn’t too bad; but it does mean some logic is repeated in any implementation.
The non-lifecycle based logic can be extracted as such:
Date.now() <= expiresAt && expiryStatus !== ExpiryStatus.InvalidProposal
💡 Need feedback on name. I don’t like how long fetchIfStale is!Add a new controller dispatch that will only fetch if the result is stale. If it ends up not fetching the promise will immediately resolve.
- Only accepts sideEffect: false endpoints
Open questions
- what should it be called
- what should it resolve to as it might not fetch but that means the data already exists?
- maybe denormalized form and waits until commit.
- or perhaps the resolve value lets you know if it fetched at all
- always returning a promise means it is unusable in hooks pre-react18. can we possibly hook up a callback in the middleware that determines whether it fetches non-async?
Dispatch resolution control
dispatch adds to action a callback. if this callback is called it returns the dispatch early.
Instead of
return next(action);return Whatever;And you can still continue processing the request by doing the rest of it async
// we don't wait on resolution
next(action);
return Whatever;Doing this would also enable not having to send resolve/reject in fetch meta; but just take dispatch return value. This would be actual promise used by the NetworkManager so referential equality checks could be performed against it.
This means dispatch() now has a variable return type based on what the middlewares do. This could have weird implications for user-defined managers; so perhaps we should add type inference based on middlewares? This can be delayed tho.