From fc705d31ede2f79fa26e7f5d3919739820998c68 Mon Sep 17 00:00:00 2001
From: Matt Brophy
Date: Thu, 20 Apr 2023 12:45:17 -0400
Subject: [PATCH 1/5] Fix descendant Routes rendering alongside RouterProvider
errors
---
.changeset/descendant-routes-data-errors.md | 5 ++
.../__tests__/data-memory-router-test.tsx | 55 +++++++++++++++++--
packages/react-router/lib/hooks.tsx | 12 +++-
3 files changed, 64 insertions(+), 8 deletions(-)
create mode 100644 .changeset/descendant-routes-data-errors.md
diff --git a/.changeset/descendant-routes-data-errors.md b/.changeset/descendant-routes-data-errors.md
new file mode 100644
index 0000000000..0d1949df3c
--- /dev/null
+++ b/.changeset/descendant-routes-data-errors.md
@@ -0,0 +1,5 @@
+---
+"react-router": patch
+---
+
+Fix bug preventing rendering of descendant `` when `RouterProvider` errors existed
diff --git a/packages/react-router/__tests__/data-memory-router-test.tsx b/packages/react-router/__tests__/data-memory-router-test.tsx
index 2aae328224..a10618c00b 100644
--- a/packages/react-router/__tests__/data-memory-router-test.tsx
+++ b/packages/react-router/__tests__/data-memory-router-test.tsx
@@ -1019,11 +1019,6 @@ describe("createMemoryRouter", () => {
),
{
initialEntries: ["/deep/path/to/descendant/routes"],
- hydrationData: {
- loaderData: {
- "0-0": "count=1",
- },
- },
}
);
let { container } = render();
@@ -1058,6 +1053,56 @@ describe("createMemoryRouter", () => {
`);
});
+ it.only("renders alongside a data router ErrorBoundary", () => {
+ let router = createMemoryRouter(
+ [
+ {
+ path: "*",
+ Component() {
+ return (
+ <>
+
+
+ Descendant} />
+
+ >
+ );
+ },
+ children: [
+ {
+ id: "index",
+ index: true,
+ Component: () => Child
,
+ ErrorBoundary() {
+ return {(useRouteError() as Error).message}
;
+ },
+ },
+ ],
+ },
+ ],
+ {
+ initialEntries: ["/"],
+ hydrationData: {
+ errors: {
+ index: new Error("Broken!"),
+ },
+ },
+ }
+ );
+ let { container } = render();
+
+ expect(getHtml(container)).toMatchInlineSnapshot(`
+ "
+
+ Broken!
+
+
+ Descendant
+
+
"
+ `);
+ });
+
describe("errors", () => {
it("renders hydration errors on leaf elements using errorElement", async () => {
let router = createMemoryRouter(
diff --git a/packages/react-router/lib/hooks.tsx b/packages/react-router/lib/hooks.tsx
index 4568e09880..7a6740b6a7 100644
--- a/packages/react-router/lib/hooks.tsx
+++ b/packages/react-router/lib/hooks.tsx
@@ -319,6 +319,7 @@ export function useRoutes(
);
let { navigator } = React.useContext(NavigationContext);
+ let dataRouterContext = React.useContext(DataRouterContext);
let dataRouterStateContext = React.useContext(DataRouterStateContext);
let { matches: parentMatches } = React.useContext(RouteContext);
let routeMatch = parentMatches[parentMatches.length - 1];
@@ -432,7 +433,10 @@ export function useRoutes(
})
),
parentMatches,
- dataRouterStateContext || undefined
+ // Only pass along the dataRouterStateContext when we're rendering from the
+ // RouterProvider layer. If routes is different then we're rendering from
+ // a descendant tree
+ dataRouterContext?.router.routes === routes ? dataRouterStateContext : null
);
// When a user passes in a `locationArg`, the associated routes need to
@@ -613,7 +617,7 @@ function RenderedRoute({ routeContext, match, children }: RenderedRouteProps) {
export function _renderMatches(
matches: RouteMatch[] | null,
parentMatches: RouteMatch[] = [],
- dataRouterState?: RemixRouter["state"]
+ dataRouterState: RemixRouter["state"] | null = null
): React.ReactElement | null {
if (matches == null) {
if (dataRouterState?.errors) {
@@ -635,7 +639,9 @@ export function _renderMatches(
);
invariant(
errorIndex >= 0,
- `Could not find a matching route for the current errors: ${errors}`
+ `Could not find a matching route for errors on route IDs: ${Object.keys(
+ errors
+ ).join(",")}`
);
renderedMatches = renderedMatches.slice(
0,
From f1d1e936d664add79b0adae5bba533c7dc7132eb Mon Sep 17 00:00:00 2001
From: Matt Brophy
Date: Thu, 20 Apr 2023 14:51:36 -0400
Subject: [PATCH 2/5] Remove it.only
---
.../__tests__/data-memory-router-test.tsx | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/packages/react-router/__tests__/data-memory-router-test.tsx b/packages/react-router/__tests__/data-memory-router-test.tsx
index a10618c00b..1f67ec2384 100644
--- a/packages/react-router/__tests__/data-memory-router-test.tsx
+++ b/packages/react-router/__tests__/data-memory-router-test.tsx
@@ -1053,7 +1053,7 @@ describe("createMemoryRouter", () => {
`);
});
- it.only("renders alongside a data router ErrorBoundary", () => {
+ it("renders alongside a data router ErrorBoundary", () => {
let router = createMemoryRouter(
[
{
@@ -1806,14 +1806,14 @@ describe("createMemoryRouter", () => {
💿 Hey developer 👋
- You can provide a way better UX than this when your app throws errors by providing your own
+ You can provide a way better UX than this when your app throws errors by providing your own
ErrorBoundary
or
-
+
@@ -1925,14 +1925,14 @@ describe("createMemoryRouter", () => {
💿 Hey developer 👋
- You can provide a way better UX than this when your app throws errors by providing your own
+ You can provide a way better UX than this when your app throws errors by providing your own
ErrorBoundary
or
-
+
@@ -2159,14 +2159,14 @@ describe("createMemoryRouter", () => {
💿 Hey developer 👋
- You can provide a way better UX than this when your app throws errors by providing your own
+ You can provide a way better UX than this when your app throws errors by providing your own
ErrorBoundary
or
-
+
@@ -2345,14 +2345,14 @@ describe("createMemoryRouter", () => {
💿 Hey developer 👋
- You can provide a way better UX than this when your app throws errors by providing your own
+ You can provide a way better UX than this when your app throws errors by providing your own
ErrorBoundary
or
-
+
From 90a1851fc8e278016c8e5917a697998a6e3819e9 Mon Sep 17 00:00:00 2001
From: Matt Brophy
Date: Thu, 20 Apr 2023 15:10:42 -0400
Subject: [PATCH 3/5] Remove fork from Routes in favor of new DataRoutes
component
---
packages/react-router-dom/server.tsx | 19 ++++++++++++++++---
packages/react-router/lib/components.tsx | 24 ++++++++++++++----------
2 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/packages/react-router-dom/server.tsx b/packages/react-router-dom/server.tsx
index e89006e066..8b21110069 100644
--- a/packages/react-router-dom/server.tsx
+++ b/packages/react-router-dom/server.tsx
@@ -18,12 +18,17 @@ import {
UNSAFE_convertRoutesToDataRoutes as convertRoutesToDataRoutes,
} from "@remix-run/router";
import { UNSAFE_mapRouteProperties as mapRouteProperties } from "react-router";
-import type { Location, RouteObject, To } from "react-router-dom";
-import { Routes } from "react-router-dom";
+import type {
+ DataRouteObject,
+ Location,
+ RouteObject,
+ To,
+} from "react-router-dom";
import {
createPath,
parsePath,
Router,
+ useRoutes,
UNSAFE_DataRouterContext as DataRouterContext,
UNSAFE_DataRouterStateContext as DataRouterStateContext,
} from "react-router-dom";
@@ -127,7 +132,7 @@ export function StaticRouterProvider({
navigationType={dataRouterContext.router.state.historyAction}
navigator={dataRouterContext.navigator}
>
-
+
@@ -142,6 +147,14 @@ export function StaticRouterProvider({
);
}
+function DataRoutes({
+ routes,
+}: {
+ routes: DataRouteObject[];
+}): React.ReactElement | null {
+ return useRoutes(routes);
+}
+
function serializeErrors(
errors: StaticHandlerContext["errors"]
): StaticHandlerContext["errors"] {
diff --git a/packages/react-router/lib/components.tsx b/packages/react-router/lib/components.tsx
index 7cdd4c083b..e5c9949dc8 100644
--- a/packages/react-router/lib/components.tsx
+++ b/packages/react-router/lib/components.tsx
@@ -116,7 +116,11 @@ export function RouterProvider({
navigationType={router.state.historyAction}
navigator={navigator}
>
- {router.state.initialized ? : fallbackElement}
+ {router.state.initialized ? (
+
+ ) : (
+ fallbackElement
+ )}
@@ -125,6 +129,14 @@ export function RouterProvider({
);
}
+function DataRoutes({
+ routes,
+}: {
+ routes: DataRouteObject[];
+}): React.ReactElement | null {
+ return useRoutes(routes);
+}
+
export interface MemoryRouterProps {
basename?: string;
children?: React.ReactNode;
@@ -393,15 +405,7 @@ export function Routes({
children,
location,
}: RoutesProps): React.ReactElement | null {
- let dataRouterContext = React.useContext(DataRouterContext);
- // When in a DataRouterContext _without_ children, we use the router routes
- // directly. If we have children, then we're in a descendant tree and we
- // need to use child routes.
- let routes =
- dataRouterContext && !children
- ? (dataRouterContext.router.routes as DataRouteObject[])
- : createRoutesFromChildren(children);
- return useRoutes(routes, location);
+ return useRoutes(createRoutesFromChildren(children), location);
}
export interface AwaitResolveRenderFunction {
From 146237abda96bff9cd83384be500466417524b1f Mon Sep 17 00:00:00 2001
From: Matt Brophy
Date: Thu, 20 Apr 2023 15:11:17 -0400
Subject: [PATCH 4/5] Revert whitespace snapshot changes
---
.../__tests__/data-memory-router-test.tsx | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/packages/react-router/__tests__/data-memory-router-test.tsx b/packages/react-router/__tests__/data-memory-router-test.tsx
index 1f67ec2384..95ceccb183 100644
--- a/packages/react-router/__tests__/data-memory-router-test.tsx
+++ b/packages/react-router/__tests__/data-memory-router-test.tsx
@@ -1806,14 +1806,14 @@ describe("createMemoryRouter", () => {
💿 Hey developer 👋
- You can provide a way better UX than this when your app throws errors by providing your own
+ You can provide a way better UX than this when your app throws errors by providing your own
ErrorBoundary
or
-
+
@@ -1925,14 +1925,14 @@ describe("createMemoryRouter", () => {
💿 Hey developer 👋
- You can provide a way better UX than this when your app throws errors by providing your own
+ You can provide a way better UX than this when your app throws errors by providing your own
ErrorBoundary
or
-
+
@@ -2159,14 +2159,14 @@ describe("createMemoryRouter", () => {
💿 Hey developer 👋
- You can provide a way better UX than this when your app throws errors by providing your own
+ You can provide a way better UX than this when your app throws errors by providing your own
ErrorBoundary
or
-
+
@@ -2345,14 +2345,14 @@ describe("createMemoryRouter", () => {
💿 Hey developer 👋
- You can provide a way better UX than this when your app throws errors by providing your own
+ You can provide a way better UX than this when your app throws errors by providing your own
ErrorBoundary
or
-
+
From 8602a25ad2f04cd70f14d11f0c8a9b3e68835264 Mon Sep 17 00:00:00 2001
From: Matt Brophy
Date: Thu, 20 Apr 2023 15:21:54 -0400
Subject: [PATCH 5/5] bump bundle
---
package.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/package.json b/package.json
index 8b95a2d15f..fb87fd7997 100644
--- a/package.json
+++ b/package.json
@@ -108,10 +108,10 @@
"none": "45 kB"
},
"packages/react-router/dist/react-router.production.min.js": {
- "none": "13.3 kB"
+ "none": "13.4 kB"
},
"packages/react-router/dist/umd/react-router.production.min.js": {
- "none": "15.6 kB"
+ "none": "15.7 kB"
},
"packages/react-router-dom/dist/react-router-dom.production.min.js": {
"none": "11.8 kB"