Skip to content

Commit bf679c4

Browse files
authored
useRoutes: add support for location override (#7989)
* useRoutes: add support for location override - Resolves #7117
1 parent caf3c85 commit bf679c4

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

packages/react-router/__tests__/useRoutes-test.tsx

+30-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import * as React from "react";
2+
import * as ReactDOM from "react-dom";
23
import { create as createTestRenderer } from "react-test-renderer";
34
import { MemoryRouter as Router, useRoutes } from "react-router";
5+
import { act } from "react-dom/test-utils";
46
import type { PartialRouteObject } from "react-router";
57

68
describe("useRoutes", () => {
@@ -26,14 +28,40 @@ describe("useRoutes", () => {
2628

2729
expect(renderer.toJSON()).toMatchSnapshot();
2830
});
31+
32+
it("Uses the `location` prop instead of context location`", () => {
33+
let node = document.createElement("div");
34+
document.body.appendChild(node);
35+
36+
let routes = [
37+
{ path: "one", element: <h1>one</h1> },
38+
{ path: "two", element: <h1>two</h1> }
39+
];
40+
41+
act(() => {
42+
ReactDOM.render(
43+
<Router initialEntries={["/one"]}>
44+
<RoutesRenderer routes={routes} location={{ pathname: "/two" }} />
45+
</Router>,
46+
node
47+
);
48+
});
49+
50+
expect(node.innerHTML).toMatch(/two/);
51+
52+
// cleanup
53+
document.body.removeChild(node);
54+
});
2955
});
3056

3157
function RoutesRenderer({
3258
routes,
33-
basename
59+
basename,
60+
location
3461
}: {
3562
routes: PartialRouteObject[];
3663
basename?: string;
64+
location?: Partial<Location> & { pathname: string };
3765
}) {
38-
return useRoutes(routes, basename);
66+
return useRoutes(routes, basename, location);
3967
}

packages/react-router/index.tsx

+14-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import type {
66
InitialEntry,
77
Location,
88
MemoryHistory,
9-
PartialLocation,
109
Path,
1110
State,
1211
To,
@@ -250,10 +249,15 @@ export function Router({
250249
);
251250
}
252251

252+
interface PartialLocation<S extends State = State>
253+
extends Omit<Partial<Location<S>>, "pathname"> {
254+
pathname: string;
255+
}
256+
253257
export interface RoutesProps {
254258
basename?: string;
255259
children?: React.ReactNode;
256-
location?: Location;
260+
location?: PartialLocation;
257261
}
258262

259263
/**
@@ -268,8 +272,7 @@ export function Routes({
268272
location
269273
}: RoutesProps): React.ReactElement | null {
270274
let routes = createRoutesFromChildren(children);
271-
let location_ = useLocation();
272-
return useRoutes_(routes, location ?? location_, basename);
275+
return useRoutes_(routes, location, basename);
273276
}
274277

275278
///////////////////////////////////////////////////////////////////////////////
@@ -492,7 +495,8 @@ export function useResolvedPath(to: To): Path {
492495
*/
493496
export function useRoutes(
494497
partialRoutes: PartialRouteObject[],
495-
basename = ""
498+
basename = "",
499+
location?: PartialLocation
496500
): React.ReactElement | null {
497501
invariant(
498502
useInRouterContext(),
@@ -501,7 +505,6 @@ export function useRoutes(
501505
`useRoutes() may be used only in the context of a <Router> component.`
502506
);
503507

504-
let location = useLocation();
505508
let routes = React.useMemo(
506509
() => createRoutesFromArray(partialRoutes),
507510
[partialRoutes]
@@ -512,7 +515,7 @@ export function useRoutes(
512515

513516
function useRoutes_(
514517
routes: RouteObject[],
515-
location: Location,
518+
locationOverride?: PartialLocation,
516519
basename = ""
517520
): React.ReactElement | null {
518521
let {
@@ -543,6 +546,9 @@ function useRoutes_(
543546
? joinPaths([parentPathname, basename])
544547
: parentPathname;
545548

549+
let contextLocation = useLocation();
550+
let location = locationOverride ?? contextLocation;
551+
546552
let matches = React.useMemo(
547553
() => matchRoutes(routes, location, basenameForMatching),
548554
[location, routes, basenameForMatching]
@@ -703,7 +709,7 @@ export function generatePath(path: string, params: Params = {}): string {
703709
*/
704710
export function matchRoutes(
705711
routes: PartialRouteObject[],
706-
location: string | PartialLocation,
712+
location: string | Partial<Location>,
707713
basename = ""
708714
): RouteMatch[] | null {
709715
if (typeof location === "string") {

0 commit comments

Comments
 (0)