-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update Remix to use route.lazy from React Router #7133
Conversation
🦋 Changeset detectedLatest commit: 67fa0f3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
window.location.reload(); | ||
// Get out of here so the reload can happen - don't create the router | ||
// since it'll then kick off unnecessary route.lazy() loads | ||
return <></>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this we get into I think the same hydration error loop as #1678. I hope to dig deeper into that later today/tomorrow so maybe it'll shed some light on why we need the short circuit, but once I move this up and return (and avoid any router initialization + lazy calls on the wrong route) the E2E test passes and all of my manual testing with rapid forward clicks into a Remix app to cause a mismatched URL at hydration time settle correctly on the final URL after the hard reload.
//////////////////////////////////////////////////////////////////////////////// | ||
// RemixRoute | ||
|
||
export function RemixRoute({ id }: { id: string }) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RemixRoute
and RemixRouteError
were sort of poor-mans implementations of Component
/ErrorBoundary
lazy loading. We could assign them to a route definition up front (without a route module available) knowing that they'd pull from the lazily loaded routeModulesCache
at render-time. Now we can just assign Component
/ErrorBoundary
via lazy()
.
The only downside is we lose these error messages - so if we think they are worth keeping we can stick with this approach.
// Need to grab handle here since we don't have it at client-side route | ||
// creation time | ||
handle: routeModules[match.id].handle, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer need to grab handle
from the routeModulesCache
since it's populated via lazy()
loader({ request }) { | ||
if (!route.hasLoader) return null; | ||
return fetchServerHandler(request, route); | ||
}, | ||
action({ request }) { | ||
if (!route.hasAction) { | ||
let msg = | ||
`Route "${route.id}" does not have an action, but you are trying ` + | ||
`to submit to it. To fix this, please add an \`action\` function to the route`; | ||
console.error(msg); | ||
return Promise.reject(new Error(msg)); | ||
} | ||
|
||
return fetchServerHandler(request, route); | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lifted the forked logic from createDataFunction
to inline here so we can share 100% of fetchServerHandler
...(routeModule | ||
? // Use critical path modules directly | ||
{ | ||
Component: routeModule.default, | ||
ErrorBoundary: routeModule.ErrorBoundary | ||
? routeModule.ErrorBoundary | ||
: route.id === "root" | ||
? () => <RemixRootDefaultErrorBoundary error={useRouteError()} /> | ||
: undefined, | ||
handle: routeModule.handle, | ||
shouldRevalidate: needsRevalidation | ||
? wrapShouldRevalidateForHdr( | ||
route.id, | ||
routeModule.shouldRevalidate, | ||
needsRevalidation | ||
) | ||
: routeModule.shouldRevalidate, | ||
} | ||
: // Load all other modules via route.lazy() | ||
{ | ||
lazy: async () => { | ||
let mod = await loadRouteModuleWithBlockingLinks( | ||
route, | ||
routeModulesCache | ||
); | ||
if (needsRevalidation) { | ||
mod.shouldRevalidate = wrapShouldRevalidateForHdr( | ||
route.id, | ||
mod.shouldRevalidate, | ||
needsRevalidation | ||
); | ||
} | ||
return mod; | ||
}, | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the meat of this PR - non-critical routes get everything populated via lazy
now
8b9c0f3
to
a543449
Compare
🤖 Hello there, We just published version Thanks! |
🤖 Hello there, We just published version Thanks! |
Leverage
route.lazy
from React RouterTODO: