Add onPrefetch
to Link
#12375
Replies: 7 comments 5 replies
-
Within data routers (library mode), it would be super cool if the default prefetch behavior was to invoke the loader for the target href. This would encapsulate data loading particulars within the route and encourage the pattern of fetching/prefetching in the loader to prime the cache, closer to where the query results are used. But this could totally be a userland thing too: function useLinkPrefetcher({ to, prefetch }: Pick<LinkProps, 'to' | 'prefetch'>, key?: string) {
const href = useHref(to);
const { load } = useFetcher({ key: key ?? `preload/${to}` });
return useMemo(() => {
return prefetch ? () => load(href) : undefined;
}, [href, load, prefetch]);
} |
Beta Was this translation helpful? Give feedback.
-
Great that this is being proposed!
I don't think this is necessarily a safe assumption. There could be things in scope in the route module available to be used in the client loader that are not in scope everywhere a It would be great to have the option to call the client loader if desired, for instance if |
Beta Was this translation helpful? Give feedback.
-
Related/Duplicate Proposal: #14187 |
Beta Was this translation helpful? Give feedback.
-
We are going to move forward with this. Adding the |
Beta Was this translation helpful? Give feedback.
-
Related proposal closed in favor of this one #8012 |
Beta Was this translation helpful? Give feedback.
-
Suggestion: Route-level preloading.Rather than placing preloading logic in the Link component, I believe this functionality should be exported from routes themselves. This ensures that every reference to a route automatically preloads, eliminating the need to wrap React Router's Link component in userland. Here's an implementation using the https://reactrouter.com/start/framework/route-module#handle: In your route file: export const handle = {
async intent() {
// do anything.
}
};
export default function Component() { /* ... */ } In your link component: import { Link, matchRoutes } from "react-router";
function IntentfulLink({ to, children }) {
let intent = React.useCallback(async () => {
// @ts-expect-error: React Router internal.
const matches = matchRoutes(globalThis.__reactRouterDataRouter.routes, to) || [];
await Promise.all(matches.map(async ({ route }) => {
// @ts-expect-error: React Router internal.
const handle = route.handle || await route.lazy?.handle();
if (!handle || typeof handle !== "object" || !handle.intent) return null;
return handle.intent();
}));
}, [to]);
return (
<Link to={to} onMouseOver={intent}>
{children}
</Link>
);
} |
Beta Was this translation helpful? Give feedback.
-
Will there be an option to simply call the loader? I think many tanstack query users (including me) would appreciate not having to duplicate data loading code |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
We can prefetch loader data because we simply use html
<link rel="prefetch" />
and then the browser manages the cache with HTTP. We get feature requests to prefetch client loaders too but then we'd need a cache to store them (and expire them) etc.Instead, I think we can add a very simple event to links:
onPrefetch
.Apps can simply do whatever they'd like there, probably call
prefetch
on whatever cache they're using (like React Query).This way we can still prefetch the JS modules and they can prefetch everything else.
Signature
I don't think it needs any arguments because they should have everything they need in scope already:
Beta Was this translation helpful? Give feedback.
All reactions