Repository navigation
Replies: 1 comment
|
Closing in favor of the canonical custom-fetch proposal, being implemented in PR #15586. The proposed The context describes the triggering operation, not simply whether the URL changes: a same-route navigating The implementation PR is still open; follow #15461/#15586 for progress. Authored by an AI agent on behalf of @brophdawg11 |
Uh oh!
There was an error while loading. Please reload this page.
Summary
Add a public, non-breaking
X-React-Router-Request-Intentrequest header to data requests so loaders, actions, and middleware can distinguish navigation requests (the user is moving to a new route) from fetch requests (the user stays put — revalidations,useFetcherloads/submits, and form submissions to the current route).Splitting this out from #14505 per the suggestion to scope a separate RFC for request-type detection.
Motivation: auth-redirect target selection
In our app every loader/middleware may hit a redirect-through-the-auth-provider flow. After the round-trip the app must decide where to land the user, and the correct destination depends on the intent of the original request:
request.url. Redirect there.Referer. Redirect there to preserve their visual location.Today there is no reliable way to tell these apart on the server.
request.urland the_routesquery param are not enough —useRevalidator(),useFetcher().load(...), and a<Link>navigation can all produce the same-shaped URL.We currently handle this with a client-side patch that adds the header (link in the Reference Patch section). This RFC proposes adopting it into the framework.
Scenarios
User is on
/dashboardunless noted. Each scenario assumes the request hits an expired session and triggers the auth round-trip./dashboardGET /dashboard/dashboard<Link to="/settings">clickedGET /settings.data?_routes=…/settingsuseRevalidator()GET /dashboard.data?_routes=…Referer(/dashboard)useFetcher().load("/users")GET /users.data?_routes=…Referer(/dashboard) — user does not land on/users<Form method="post">to current routePOST /dashboard.data?_routes=…Referer; preserve/replay form stateuseFetcher().submit(…)POST /target.data?_routes=…Referer; preserve/replay form state/parent/a→/parent/b)GET /parent/b.data?_routes=root,parent,b/parent/b(single target for the batch)Cases 3 and 4 are the ones that are impossible to disambiguate from case 2 today.
Proposed API
A request header set client-side by the router on data requests:
navigation— originated from a navigation (<Link>,navigate(),<Form>to a different route, etc).fetch— originated from anything that does not change the user's location:useRevalidator(),useFetcher().load/submit,<Form>submitted to the current route.Document requests do not need the header — they can always be treated as navigation requests. The header exists only on
.datarequests, where the ambiguity is. The proposal in #14505 helps us distinguish betweendocumentvs.datarequests.Read in loaders/actions/middleware via
request.headers.get("X-React-Router-Request-Intent").Reference patch
cerbos/react-router @ 8702c05. The patch uses the header name
X-Request-Type; this RFC proposesX-React-Router-Request-Intentto align with existing framework-owned headers.Behaviour:
createClientSideRequestaddsfetchwhen the header is missing.startNavigationacceptsopts.isRevalidation; when falsy it addsnavigation. When truthy it leaves the header alone, so the request falls through tocreateClientSideRequestand is taggedfetch.revalidatealways passesisRevalidation: truetostartNavigation.Net result: navigations get
navigation, everything else (revalidations, fetcher loads/submits, current-route form submissions) getsfetch. Manual testing confirmed correct values for all of those. Happy to bring this to PR quality with full test coverage if there's interest.All reactions