Skip to content

Commit

Permalink
chore: Merge branch 'main' into release/v6.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
chaance committed Feb 28, 2022
2 parents 53a04c5 + 347f4fe commit e2712c4
Show file tree
Hide file tree
Showing 15 changed files with 190 additions and 60 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:

jobs:
format:
if: github.repository == 'remix-run/react-router'
runs-on: ubuntu-latest

steps:
Expand Down Expand Up @@ -40,6 +41,6 @@ jobs:
echo "💿 no formatting changed"
exit 0
fi
git commit -m "chore: format" -m "formatted $GITHUB_SHA"
git commit -m "chore: format"
git push
echo "💿 pushed formatting changes https://github.com/$GITHUB_REPOSITORY/commit/$(git rev-parse HEAD)"
23 changes: 23 additions & 0 deletions CLA.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Remix Software, Inc. Individual Contributor License Agreement ("Agreement"), v2.0

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.

1. Definitions.

"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.

"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."

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.

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.

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.

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.

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.

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]".

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.
18 changes: 18 additions & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,47 @@
- abhi-kr-2100
- Ajayff4
- awreese
- bhbs
- BrianT1414
- brockross
- brophdawg11
- chaance
- chasinhues
- chrisngobanh
- christopherchudzicki
- cvbuelow
- edwin177
- elylucas
- hongji00
- hsbtr
- hyesungoh
- IbraRouisDev
- Isammoc
- JakubDrozd
- jmargeta
- jonkoops
- kantuni
- kddnewton
- kentcdodds
- kkirsche
- koojaa
- latin-1
- liuhanqu
- lukerSpringTree
- markivancho
- mcansh
- noisypigeon
- paulsmithkc
- petersendidit
- RobHannay
- sanketshah19
- sergiodxa
- shamsup
- shihanng
- shivamsinghchahar
- thisiskartik
- timdorr
- turansky
- underager
- vijaypushkin
- KutnerUri
100 changes: 71 additions & 29 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ To get React Router working in your app, you need to render a router element at
- [`<StaticRouter>`](#staticrouter) should be used when server-rendering a website
- [`<NativeRouter>`](#nativerouter) should be used in [React Native](https://reactnative.dev/) apps
- [`<MemoryRouter>`](#memoryrouter) is useful in testing scenarios and as a reference implementation for the other routers
- [`<unstable_HistoryRouter>`](#unstable_historyrouter) is used with your own [`history`](https://github.com/remix-run/history) instance.

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.

Expand Down Expand Up @@ -233,6 +234,45 @@ describe("My app", () => {
});
```

### `<unstable_HistoryRouter>`

<details>
<summary>Type declaration</summary>

```tsx
declare function HistoryRouter(
props: HistoryRouterProps
): React.ReactElement;

interface HistoryRouterProps {
basename?: string;
children?: React.ReactNode;
history: History;
}
```

</details>

`<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.

```tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import { createBrowserHistory } from "history";

const history = createBrowserHistory({ window });

ReactDOM.render(
<HistoryRouter history={history}>
{/* The rest of your app goes here */}
</HistoryRouter>,
root
);
```

<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>

### `<Link>`

> **Note:**
Expand Down Expand Up @@ -310,7 +350,7 @@ interface LinkProps extends TouchableHighlightProps {
children?: React.ReactNode;
onPress?(event: GestureResponderEvent): void;
replace?: boolean;
state?: State;
state?: any;
to: To;
}
```
Expand Down Expand Up @@ -355,7 +395,9 @@ interface NavLinkProps
| ((props: { isActive: boolean }) => React.ReactNode);
className?:
| string
| ((props: { isActive: boolean }) => string);
| ((props: {
isActive: boolean;
}) => string | undefined);
end?: boolean;
style?:
| React.CSSProperties
Expand Down Expand Up @@ -473,7 +515,7 @@ declare function Navigate(props: NavigateProps): null;
interface NavigateProps {
to: To;
replace?: boolean;
state?: State;
state?: any;
}
```

Expand Down Expand Up @@ -594,6 +636,8 @@ function Parent() {
```

```tsx lines=[2]
import { useOutletContext } from "react-router-dom";

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

type ContextType = { user: User | null };

Expand All @@ -615,7 +660,7 @@ export default function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<Outlet context={user} />
<Outlet context={{ user }} />
</div>
);
}
Expand All @@ -629,7 +674,7 @@ export function useUser() {
import { useUser } from "../dashboard";

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

```tsx
declare function useLinkClickHandler<
E extends Element = HTMLAnchorElement,
S extends State = State
E extends Element = HTMLAnchorElement
>(
to: To,
options?: {
target?: React.HTMLAttributeAnchorTarget;
replace?: boolean;
state?: S;
state?: any;
}
): (event: React.MouseEvent<E, MouseEvent>) => void;
```
Expand Down Expand Up @@ -1025,13 +1069,11 @@ const Link = React.forwardRef(
<summary>Type declaration</summary>

```tsx
declare function useLinkPressHandler<
S extends State = State
>(
declare function useLinkPressHandler(
to: To,
options?: {
replace?: boolean;
state?: S;
state?: any;
}
): (event: GestureResponderEvent) => void;
```
Expand Down Expand Up @@ -1091,9 +1133,8 @@ The `useInRouterContext` hooks returns `true` if the component is being rendered
```tsx
declare function useLocation(): Location;

interface Location<S extends State = object | null>
extends Path {
state: S;
interface Location extends Path {
state: unknown;
key: Key;
}
```
Expand Down Expand Up @@ -1315,7 +1356,7 @@ function App() {
```tsx
declare function useSearchParams(
defaultInit?: URLSearchParamsInit
): [URLSearchParams, URLSearchParamsSetter];
): [URLSearchParams, SetURLSearchParams];

type ParamKeyValuePair = [string, string];

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

interface URLSearchParamsSetter {
(
nextInit: URLSearchParamsInit,
navigateOptions?: { replace?: boolean; state?: State }
): void;
}
type SetURLSearchParams = (
nextInit?: URLSearchParamsInit,
navigateOpts?: : { replace?: boolean; state?: any }
) => void;
```

</details>
Expand Down Expand Up @@ -1381,7 +1420,7 @@ function App() {
```tsx
declare function useSearchParams(
defaultInit?: URLSearchParamsInit
): [URLSearchParams, URLSearchParamsSetter];
): [URLSearchParams, SetURLSearchParams];

type ParamKeyValuePair = [string, string];

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

interface URLSearchParamsSetter {
(
nextInit: URLSearchParamsInit,
navigateOptions?: { replace?: boolean; state?: State }
): void;
type SetURLSearchParams = (
nextInit?: URLSearchParamsInit,
navigateOpts?: : NavigateOptions
) => void;

interface NavigateOptions {
replace?: boolean;
state?: any;
}
```

Expand Down
10 changes: 5 additions & 5 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function withRouter(Component) {

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

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.
We mentioned this [in the migration guide from v5 to v6](./upgrading/v5.md#advantages-of-route-element), but it's worth repeating here.

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

Expand Down Expand Up @@ -296,9 +296,9 @@ These are all actually just static paths, so in v6 you can make three routes and
function App() {
return (
<Routes>
<Route path="en" element={<Lang code="en" />} />
<Route path="es" element={<Lang code="en" />} />
<Route path="fr" element={<Lang code="en" />} />
<Route path="en" element={<Lang lang="en" />} />
<Route path="es" element={<Lang lang="es" />} />
<Route path="fr" element={<Lang lang="fr" />} />
</Routes>
);
}
Expand Down Expand Up @@ -335,7 +335,7 @@ function App() {
return (
<Routes>
<Route path="/users/:id" element={<ValidateUser />} />
<Route path="/users/*" component={NotFound} />
<Route path="/users/*" element={<NotFound />} />
</Routes>
);
}
Expand Down
10 changes: 5 additions & 5 deletions docs/getting-started/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ React Router takes advantage of this browser feature, abstracts it a bit, and su

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.

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

- 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).
- 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).
- 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.

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

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

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.
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.

### Match Params

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

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.

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.
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.

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.

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

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.

However, links are accessible in that they
However, links are accessible in that they:

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

0 comments on commit e2712c4

Please sign in to comment.