Skip to content

Commit e2712c4

Browse files
committed
chore: Merge branch 'main' into release/v6.2.2
2 parents 53a04c5 + 347f4fe commit e2712c4

File tree

15 files changed

+190
-60
lines changed

15 files changed

+190
-60
lines changed

.github/workflows/format.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88

99
jobs:
1010
format:
11+
if: github.repository == 'remix-run/react-router'
1112
runs-on: ubuntu-latest
1213

1314
steps:
@@ -40,6 +41,6 @@ jobs:
4041
echo "💿 no formatting changed"
4142
exit 0
4243
fi
43-
git commit -m "chore: format" -m "formatted $GITHUB_SHA"
44+
git commit -m "chore: format"
4445
git push
4546
echo "💿 pushed formatting changes https://github.com/$GITHUB_REPOSITORY/commit/$(git rev-parse HEAD)"

CLA.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Remix Software, Inc. Individual Contributor License Agreement ("Agreement"), v2.0
2+
3+
You accept and agree to the following terms and conditions for Your present and future Contributions submitted to Remix Software, Inc. ("Remix"). Except for the license granted herein to Remix and recipients of software distributed by Remix, You reserve all right, title, and interest in and to Your Contributions.
4+
5+
1. Definitions.
6+
7+
"You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with Remix. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
8+
9+
"Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to Remix for inclusion in, or documentation of, any of the products owned or managed by Remix (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to Remix or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, Remix for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
10+
11+
2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to Remix and to recipients of software distributed by Remix a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.
12+
13+
3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to Remix and to recipients of software distributed by Remix a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.
14+
15+
4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to Remix, or that your employer has executed a separate Corporate CLA with Remix.
16+
17+
5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions.
18+
19+
6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
20+
21+
7. Should You wish to submit work that is not Your original creation, You may submit it to Remix separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]".
22+
23+
8. You agree to notify Remix of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.

contributors.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,47 @@
1+
- abhi-kr-2100
12
- Ajayff4
3+
- awreese
4+
- bhbs
5+
- BrianT1414
26
- brockross
37
- brophdawg11
48
- chaance
9+
- chasinhues
510
- chrisngobanh
11+
- christopherchudzicki
12+
- cvbuelow
13+
- edwin177
614
- elylucas
715
- hongji00
16+
- hsbtr
17+
- hyesungoh
18+
- IbraRouisDev
819
- Isammoc
920
- JakubDrozd
21+
- jmargeta
1022
- jonkoops
23+
- kantuni
1124
- kddnewton
1225
- kentcdodds
1326
- kkirsche
27+
- koojaa
1428
- latin-1
1529
- liuhanqu
30+
- lukerSpringTree
1631
- markivancho
1732
- mcansh
1833
- noisypigeon
1934
- paulsmithkc
2035
- petersendidit
2136
- RobHannay
37+
- sanketshah19
2238
- sergiodxa
2339
- shamsup
40+
- shihanng
2441
- shivamsinghchahar
2542
- thisiskartik
2643
- timdorr
2744
- turansky
45+
- underager
2846
- vijaypushkin
2947
- KutnerUri

docs/api.md

Lines changed: 71 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ To get React Router working in your app, you need to render a router element at
2929
- [`<StaticRouter>`](#staticrouter) should be used when server-rendering a website
3030
- [`<NativeRouter>`](#nativerouter) should be used in [React Native](https://reactnative.dev/) apps
3131
- [`<MemoryRouter>`](#memoryrouter) is useful in testing scenarios and as a reference implementation for the other routers
32+
- [`<unstable_HistoryRouter>`](#unstable_historyrouter) is used with your own [`history`](https://github.com/remix-run/history) instance.
3233

3334
These routers provide the context that React Router needs to operate in a particular environment. Each one renders [a `<Router>`](#router) internally, which you may also do if you need more fine-grained control for some reason. But it is highly likely that one of the built-in routers is what you need.
3435

@@ -233,6 +234,45 @@ describe("My app", () => {
233234
});
234235
```
235236

237+
### `<unstable_HistoryRouter>`
238+
239+
<details>
240+
<summary>Type declaration</summary>
241+
242+
```tsx
243+
declare function HistoryRouter(
244+
props: HistoryRouterProps
245+
): React.ReactElement;
246+
247+
interface HistoryRouterProps {
248+
basename?: string;
249+
children?: React.ReactNode;
250+
history: History;
251+
}
252+
```
253+
254+
</details>
255+
256+
`<unstable_HistoryRouter>` takes an instance of the [`history`](https://github.com/remix-run/history) library as prop. This allows you to use that instance in non-React contexts or as a global variable.
257+
258+
```tsx
259+
import * as React from "react";
260+
import * as ReactDOM from "react-dom";
261+
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
262+
import { createBrowserHistory } from "history";
263+
264+
const history = createBrowserHistory({ window });
265+
266+
ReactDOM.render(
267+
<HistoryRouter history={history}>
268+
{/* The rest of your app goes here */}
269+
</HistoryRouter>,
270+
root
271+
);
272+
```
273+
274+
<docs-warning>This API is currently prefixed as `unstable_` because you may unintentionally add two versions of the `history` library to your app, the one you have added to your package.json and whatever version React Router uses internally. If it is allowed by your tooling, it's recommended to not add `history` as a direct dependency and instead rely on the nested dependency from the `react-router` package. Once we have a mechanism to detect mis-matched versions, this API will remove its `unstable_` prefix.</docs-warning>
275+
236276
### `<Link>`
237277

238278
> **Note:**
@@ -310,7 +350,7 @@ interface LinkProps extends TouchableHighlightProps {
310350
children?: React.ReactNode;
311351
onPress?(event: GestureResponderEvent): void;
312352
replace?: boolean;
313-
state?: State;
353+
state?: any;
314354
to: To;
315355
}
316356
```
@@ -355,7 +395,9 @@ interface NavLinkProps
355395
| ((props: { isActive: boolean }) => React.ReactNode);
356396
className?:
357397
| string
358-
| ((props: { isActive: boolean }) => string);
398+
| ((props: {
399+
isActive: boolean;
400+
}) => string | undefined);
359401
end?: boolean;
360402
style?:
361403
| React.CSSProperties
@@ -473,7 +515,7 @@ declare function Navigate(props: NavigateProps): null;
473515
interface NavigateProps {
474516
to: To;
475517
replace?: boolean;
476-
state?: State;
518+
state?: any;
477519
}
478520
```
479521

@@ -594,6 +636,8 @@ function Parent() {
594636
```
595637

596638
```tsx lines=[2]
639+
import { useOutletContext } from "react-router-dom";
640+
597641
function Child() {
598642
const [count, setCount] = useOutletContext();
599643
const increment = () => setCount((c) => c + 1);
@@ -606,6 +650,7 @@ If you're using TypeScript, we recommend the parent component provide a custom h
606650
```tsx filename=src/routes/dashboard.tsx lines=[12,17-19]
607651
import * as React from "react";
608652
import type { User } from "./types";
653+
import { Outlet, useOutletContext } from "react-router-dom";
609654

610655
type ContextType = { user: User | null };
611656

@@ -615,7 +660,7 @@ export default function Dashboard() {
615660
return (
616661
<div>
617662
<h1>Dashboard</h1>
618-
<Outlet context={user} />
663+
<Outlet context={{ user }} />
619664
</div>
620665
);
621666
}
@@ -629,7 +674,7 @@ export function useUser() {
629674
import { useUser } from "../dashboard";
630675

631676
export default function DashboardMessages() {
632-
const user = useUser();
677+
const { user } = useUser();
633678
return (
634679
<div>
635680
<h2>Messages</h2>
@@ -831,7 +876,7 @@ The term "location" in React Router refers to [the `Location` interface](https:/
831876
>
832877
> The `history` package is React Router's only dependency and many of the
833878
> core types in React Router come directly from that library including
834-
> `Location`, `To`, `Path`, `State`, and others. You can read more about
879+
> `Location`, `To`, `Path`, and others. You can read more about
835880
> the history library in [its documentation](https://github.com/remix-run/history/tree/main/docs).
836881
837882
### `matchRoutes`
@@ -958,14 +1003,13 @@ The `useHref` hook returns a URL that may be used to link to the given `to` loca
9581003

9591004
```tsx
9601005
declare function useLinkClickHandler<
961-
E extends Element = HTMLAnchorElement,
962-
S extends State = State
1006+
E extends Element = HTMLAnchorElement
9631007
>(
9641008
to: To,
9651009
options?: {
9661010
target?: React.HTMLAttributeAnchorTarget;
9671011
replace?: boolean;
968-
state?: S;
1012+
state?: any;
9691013
}
9701014
): (event: React.MouseEvent<E, MouseEvent>) => void;
9711015
```
@@ -1025,13 +1069,11 @@ const Link = React.forwardRef(
10251069
<summary>Type declaration</summary>
10261070

10271071
```tsx
1028-
declare function useLinkPressHandler<
1029-
S extends State = State
1030-
>(
1072+
declare function useLinkPressHandler(
10311073
to: To,
10321074
options?: {
10331075
replace?: boolean;
1034-
state?: S;
1076+
state?: any;
10351077
}
10361078
): (event: GestureResponderEvent) => void;
10371079
```
@@ -1091,9 +1133,8 @@ The `useInRouterContext` hooks returns `true` if the component is being rendered
10911133
```tsx
10921134
declare function useLocation(): Location;
10931135

1094-
interface Location<S extends State = object | null>
1095-
extends Path {
1096-
state: S;
1136+
interface Location extends Path {
1137+
state: unknown;
10971138
key: Key;
10981139
}
10991140
```
@@ -1315,7 +1356,7 @@ function App() {
13151356
```tsx
13161357
declare function useSearchParams(
13171358
defaultInit?: URLSearchParamsInit
1318-
): [URLSearchParams, URLSearchParamsSetter];
1359+
): [URLSearchParams, SetURLSearchParams];
13191360

13201361
type ParamKeyValuePair = [string, string];
13211362

@@ -1325,12 +1366,10 @@ type URLSearchParamsInit =
13251366
| Record<string, string | string[]>
13261367
| URLSearchParams;
13271368

1328-
interface URLSearchParamsSetter {
1329-
(
1330-
nextInit: URLSearchParamsInit,
1331-
navigateOptions?: { replace?: boolean; state?: State }
1332-
): void;
1333-
}
1369+
type SetURLSearchParams = (
1370+
nextInit?: URLSearchParamsInit,
1371+
navigateOpts?: : { replace?: boolean; state?: any }
1372+
) => void;
13341373
```
13351374

13361375
</details>
@@ -1381,7 +1420,7 @@ function App() {
13811420
```tsx
13821421
declare function useSearchParams(
13831422
defaultInit?: URLSearchParamsInit
1384-
): [URLSearchParams, URLSearchParamsSetter];
1423+
): [URLSearchParams, SetURLSearchParams];
13851424

13861425
type ParamKeyValuePair = [string, string];
13871426

@@ -1391,11 +1430,14 @@ type URLSearchParamsInit =
13911430
| Record<string, string | string[]>
13921431
| URLSearchParams;
13931432

1394-
interface URLSearchParamsSetter {
1395-
(
1396-
nextInit: URLSearchParamsInit,
1397-
navigateOptions?: { replace?: boolean; state?: State }
1398-
): void;
1433+
type SetURLSearchParams = (
1434+
nextInit?: URLSearchParamsInit,
1435+
navigateOpts?: : NavigateOptions
1436+
) => void;
1437+
1438+
interface NavigateOptions {
1439+
replace?: boolean;
1440+
state?: any;
13991441
}
14001442
```
14011443

docs/faq.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function withRouter(Component) {
3737

3838
## Why does `<Route>` have an `element` prop instead of `render` or `component`?
3939

40-
We mentioned this [in the migration guide from v5 to v6](../guides/migrating-5-to-6#advantages-of-route-element), but it's worth repeating here.
40+
We mentioned this [in the migration guide from v5 to v6](./upgrading/v5.md#advantages-of-route-element), but it's worth repeating here.
4141

4242
In React Router v6 we switched from using v5's `<Route component>` and `<Route render>` APIs to `<Route element>`. Why is that?
4343

@@ -296,9 +296,9 @@ These are all actually just static paths, so in v6 you can make three routes and
296296
function App() {
297297
return (
298298
<Routes>
299-
<Route path="en" element={<Lang code="en" />} />
300-
<Route path="es" element={<Lang code="en" />} />
301-
<Route path="fr" element={<Lang code="en" />} />
299+
<Route path="en" element={<Lang lang="en" />} />
300+
<Route path="es" element={<Lang lang="es" />} />
301+
<Route path="fr" element={<Lang lang="fr" />} />
302302
</Routes>
303303
);
304304
}
@@ -335,7 +335,7 @@ function App() {
335335
return (
336336
<Routes>
337337
<Route path="/users/:id" element={<ValidateUser />} />
338-
<Route path="/users/*" component={NotFound} />
338+
<Route path="/users/*" element={<NotFound />} />
339339
</Routes>
340340
);
341341
}

docs/getting-started/concepts.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ React Router takes advantage of this browser feature, abstracts it a bit, and su
228228

229229
You can think about `location.state` just like `location.hash` or `location.search` except instead of putting the values in the [URL](#url) it's hidden--like a super secret piece of the URL only the programmer knows about.
230230

231-
A couple great use-cases for location state are:
231+
A couple of great use-cases for location state are:
232232

233-
- Telling the next page where the user came from and branching the UI. The most popular implementation here is the showing a record in a modal if the user clicked on an item in a grid view, but if they show up to the URL directly, show the record in its own layout (pinterest, old instagram).
233+
- Telling the next page where the user came from and branching the UI. The most popular implementation here is showing a record in a modal if the user clicked on an item in a grid view, but if they show up to the URL directly, show the record in its own layout (pinterest, old instagram).
234234
- Sending a partial record from a list to the next screen so it can render the partial data immediately and then fetching the rest of the data afterward.
235235

236236
You set location state in two ways: on `<Link>` or `navigate`:
@@ -383,7 +383,7 @@ let routes = [
383383

384384
In fact, instead of `<Routes>` you can use the hook `useRoutes(routesGoHere)` instead. That's all `<Routes>` is doing.
385385

386-
As you can see, routes can define a multiple [segments](#segment) like `:teamId/edit`, or just one like `:teamId`. All of the segments down a branch of the [route config](#route-config) are added together to create a final [path pattern](#path-pattern) for a route.
386+
As you can see, routes can define multiple [segments](#segment) like `:teamId/edit`, or just one like `:teamId`. All of the segments down a branch of the [route config](#route-config) are added together to create a final [path pattern](#path-pattern) for a route.
387387

388388
### Match Params
389389

@@ -625,7 +625,7 @@ Think of it this way, if you're not at one of the child routes' paths, the `<Out
625625

626626
If all the teams are in a list on the left then an empty outlet means you've got a blank page on the right! Your UI needs something to fill the space: index routes to the rescue.
627627

628-
Another way to think of an index routes is that it's the default child route when the parent matches but none of its children do.
628+
Another way to think of an index route is that it's the default child route when the parent matches but none of its children do.
629629

630630
Depending on the user interface, you might not need an index route, but if there is any sort of persistent navigation in the parent route you'll most likely want index route to fill the space when the user hasn't clicked one of the items yet.
631631

@@ -710,7 +710,7 @@ When the [URL](#url) changes we call that a "navigation". There are two ways to
710710

711711
This is the primary means of navigation. Rendering a `<Link>` allows the user to change the URL when they click it. React Router will prevent the browser's default behavior and tell the [history](#history) to push a new entry into the [history stack](#history-stack). The [location](#location) changes and the new [matches](#match) will render.
712712

713-
However, links are accessible in that they
713+
However, links are accessible in that they:
714714

715715
- Still render a `<a href>` so all default accessibility concerns are met (like keyboard, focusability, SEO, etc.)
716716
- Don't prevent the browser's default behavior if it's a right click or command/control click to "open in new tab"

0 commit comments

Comments
 (0)