-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
RRR Step 2 - Server Rendering #4669
Conversation
|
a480bd4
to
ade8de4
Compare
49429d4
to
18e800a
Compare
This reverts commit 18e800a.
* First pass at SSR using react-router-dom@6.4 * useLoaderData/useActionData generics + useTransition/useFetcher types * Remove duped router in favor of 1.0.4-pre.0
* First pass at SSR using react-router-dom@6.4 * useLoaderData/useActionData generics + useTransition/useFetcher types * Remove duped router in favor of 1.0.4-pre.0
* First pass at SSR using react-router-dom@6.4 * useLoaderData/useActionData generics + useTransition/useFetcher types * Remove duped router in favor of 1.0.4-pre.0
* First pass at SSR using react-router-dom@6.4 * useLoaderData/useActionData generics + useTransition/useFetcher types * Remove duped router in favor of 1.0.4-pre.0
interface RemixEntryContextType { | ||
manifest: AssetsManifest; | ||
matches: BaseRouteMatch<ClientRoute>[]; | ||
routeData: RouteData; | ||
actionData?: RouteData; | ||
pendingLocation?: Location; | ||
appState: AppState; | ||
routeModules: RouteModules; | ||
serverHandoffString?: string; | ||
clientRoutes: ClientRoute[]; | ||
transitionManager: ReturnType<typeof createTransitionManager>; | ||
future: FutureConfig; |
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.
🪓 Majority of this is now handled by the router. A new RemixContext
keeps the Remix-specific things: manifest
, routeModules
, serverHandoffString
and future
. <RemixServer>
and <RemixBrowser>
render <RemixContext.Provider>
directly
</RemixCatchBoundary> | ||
</RemixErrorBoundary> | ||
</RemixEntryContext.Provider> | ||
); |
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.
buh bye <RemixEntry>
!
get data() { | ||
console.error("You cannot `useLoaderData` in an error boundary."); | ||
return undefined; | ||
}, |
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.
I think this functionality is probably still missing - should get this added to the router
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.
Bring this over to router - we will have a larger conversation about this in the future
element = ( | ||
if (!isRouteErrorResponse(error) && ErrorBoundary) { | ||
return ( | ||
// TODO: Handle error type? | ||
<RemixErrorBoundary |
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.
At the moment we just proxy through to the current RemixErrorBoundary
/RemixCatchBounary
componnts, but when we add the v2_errorBoundary
flag this function will hopefully just short circuit to return <RouteModuleErrorBoundary />
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.
post-release: Dig into why tests fail if we remve RemixErrorBoundary
in favor of <ErrorBoundary error={error}>
let { matches, routeModules, manifest } = useRemixEntryContext(); | ||
let { manifest, routeModules } = useRemixContext(); | ||
let { matches } = useDataRouterStateContext(); |
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.
Most changes to existing/preserved hooks are just grabbing stuff from the new contexts
* | ||
* @see https://remix.run/api/remix#form | ||
*/ | ||
let Form = React.forwardRef<HTMLFormElement, FormProps>((props, ref) => { |
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.
Form
, useFormAction
, useSubmit
, etc. are now re-exported from react-router-dom
}), | ||
[matches, routeData, routeModules] | ||
); | ||
} |
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 actually comes back since RR doesn't know about handle
at route definition time so needs to populate from the routeModulesCache
/** | ||
* Returns the JSON parsed data from the current route's `loader`. | ||
* | ||
* @see https://remix.run/api/remix#useloaderdata | ||
*/ | ||
export function useLoaderData<T = AppData>(): SerializeFrom<T> { | ||
return useRemixRouteContext().data; | ||
return useLoaderDataRR() as SerializeFrom<T>; |
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 current solution until we get proper generics in RR - then we can re-export directly. It felt like that was a whole undertaking unto itself though :)
import invariant from "./invariant"; | ||
import type { Submission } from "./transition"; | ||
|
||
export type AppData = any; | ||
|
||
export type FormMethod = "get" | "post" | "put" | "patch" | "delete"; | ||
export type FormMethod = FormMethodRR; |
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 something we need to do a pass on still - probably have lots of types that can either be deleted or just re-export something from RR to keep type-API compatibility
@@ -135,6 +134,7 @@ export function RemixCatchBoundary({ | |||
children, | |||
}: RemixCatchBoundaryProps) { | |||
if (catchVal) { | |||
// TODO: Add Status/Data generics to ErrorResponse? |
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.
Still outstanding
// Note: we don't need loader/action/shouldRevalidate on these routes | ||
// since they're for a static render | ||
handle: routeModules[route.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.
Server-render-time routes don't have loaders/actions since we already fetched the data!
context={context.staticHandlerContext} | ||
hydrate={false} | ||
/> | ||
</RemixContext.Provider> |
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.
👨🍳 💋
//////////////////////////////////////////////////////////////////////////////// | ||
//#region Types and Utils | ||
//////////////////////////////////////////////////////////////////////////////// | ||
import type { Location, NavigationType as Action } from "react-router-dom"; | ||
|
||
export interface CatchData<T = any> { |
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 file still exists just for typings and IDLE_TRANSITION
etc.
manifest: build.assets, | ||
routeModules: createEntryRouteModules(build.routes), | ||
serverHandoffString: createServerHandoffString(serverHandoff), | ||
staticHandlerContext: context, |
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 more appState
- just work directly with the @remix-run/router
staticHandlerContext
now
); | ||
|
||
// Restructure context.errors to the right Catch/Error Boundary | ||
differentiateCatchVersusErrorBoundaries(build, context); |
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.
Back-compat for bubbling error/catch correctly since the router doesn't have a differentiation
* First pass at SSR using react-router-dom@6.4 * useLoaderData/useActionData generics + useTransition/useFetcher types * Remove duped router in favor of 1.0.4-pre.0
Initial work towards step 2 of React Router-ing Remix
unstable_createStaticRouter
/StaticRouterProvider
<Scripts />
😉@remix-run/router
is removed in favor of1.0.4-pre.0
For branch integration testing, all SSR integration tests have been temporarily given
.only
and can be run with:For local app testing:
<Scripts />
component from your local remix app since this branch only handles server-rendering1.8.0-pre.2
into your local remix appREMIX_LOCAL_BUILD_DIRECTORY=../path/to/your/app yarn build
rm -rf node_modules/@remix-run/server-runtime/node_modules
rm -rf node_modules/@remix-run/react/node_modules
rm -rf node_modules/react-router-dom/node_modules
rm -rf node_modules/react-router/node_modules
npm run dev
Look for
✅ Rendering RR 6.4 StaticRouterProvider
in your server log to confirm that the new rendering path is applied