Skip to content

Commit

Permalink
Merge branch 'release-next' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 committed Dec 20, 2024
2 parents 2abe5f5 + c51985e commit 329fc0a
Show file tree
Hide file tree
Showing 71 changed files with 3,354 additions and 2,729 deletions.
5 changes: 0 additions & 5 deletions .changeset/dry-toes-sneeze.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/honest-dots-deliver.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/khaki-gifts-grin.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/lovely-lemons-bake.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/perfect-elephants-type.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/serious-chairs-lie.md

This file was deleted.

8 changes: 0 additions & 8 deletions .changeset/wild-dogs-double.md

This file was deleted.

259 changes: 139 additions & 120 deletions CHANGELOG.md

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
- 0xEddie
- aarbi
- abdallah-nour
- abeadam
- abhi-kr-2100
- abhijeetpandit7
- AchThomas
- acusti
- adamdotjs
Expand All @@ -17,6 +19,7 @@
- alexandernanberg
- alexanderson1993
- alexlbr
- AlexWebLab
- amitdahan
- AmRo045
- amsal
Expand All @@ -37,6 +40,7 @@
- aymanemadidi
- ayushmanchhabra
- babafemij-k
- barclayd
- bavardage
- bbrowning918
- BDomzalski
Expand Down Expand Up @@ -95,6 +99,7 @@
- fyzhu
- fz6m
- gaspard
- gavriguy
- Geist5000
- gesposito
- gianlucca
Expand Down Expand Up @@ -132,6 +137,7 @@
- jasikpark
- jasonpaulos
- jb-1980
- jclarkin
- jdufresne
- jenseng
- JeraldVin
Expand All @@ -141,6 +147,7 @@
- johnpangalos
- jonkoops
- jrakotoharisoa
- jrestall
- juanpprieto
- jungwoo3490
- kachun333
Expand All @@ -156,6 +163,7 @@
- kiliman
- kkirsche
- kno-raziel
- knownasilya
- koojaa
- KostiantynPopovych
- KubasuIvanSakwa
Expand Down Expand Up @@ -194,6 +202,7 @@
- mfijas
- MichaelDeBoey
- michal-antczak
- miguelvictor
- mikib0
- minami-minami
- minthulim
Expand Down Expand Up @@ -224,6 +233,7 @@
- pavsoldatov
- pcattori
- petersendidit
- pierophp
- printfn
- promet99
- proshunsuke
Expand All @@ -236,6 +246,7 @@
- RobHannay
- robinvdvleuten
- rtmann
- rtzll
- rubeonline
- ryanflorence
- ryanhiebert
Expand Down Expand Up @@ -284,6 +295,7 @@
- tomasr8
- tony-sn
- TooTallNate
- torztomasz
- tosinamuda
- triangularcube
- trungpv1601
Expand All @@ -299,6 +311,7 @@
- vikingviolinist
- vishwast03
- vitekzach
- vladinator1000
- vonagam
- WalkAlone0325
- whxhlgy
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/index.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
title: Explanations
order: 4
order: 5
---
4 changes: 2 additions & 2 deletions docs/explanation/race-conditions.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ The same behavior applies to form submissions. When a pending form submission is

Like the browser, interrupted navigations with links and form submissions will cancel in flight data requests and immediately process the new event.

Fetchers are a bit more nuanced since they are not singleton events like navigation. Fetchers can't interrupt a other fetcher instances, but they can interrupt themselves and the behavior is the same as everything else: cancel the interrupted request and immediately process the new one.
Fetchers are a bit more nuanced since they are not singleton events like navigation. Fetchers can't interrupt other fetcher instances, but they can interrupt themselves and the behavior is the same as everything else: cancel the interrupted request and immediately process the new one.

Fetchers do, however, interact with each when it comes to revalidation. After a fetcher's action request returns to the browser, a revalidation for all page data is sent. This means multiple revalidation requests can be in-flight at the same time. React Router will commit all "fresh" revalidation responses and cancel any stale requests. A stale request is any request that started _earlier_ than one that has returned.
Fetchers do, however, interact with each other when it comes to revalidation. After a fetcher's action request returns to the browser, a revalidation for all page data is sent. This means multiple revalidation requests can be in-flight at the same time. React Router will commit all "fresh" revalidation responses and cancel any stale requests. A stale request is any request that started _earlier_ than one that has returned.

This management of the network prevents the most common UI bugs caused by network race conditions.

Expand Down
40 changes: 40 additions & 0 deletions docs/explanation/special-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,45 @@ For an example, please refer to the default [`entry.server.tsx`][node-streaming-

Note that this does not handle thrown `Response` instances from your `loader`/`action` functions. The intention of this handler is to find bugs in your code which result in unexpected thrown errors. If you are detecting a scenario and throwing a 401/404/etc. `Response` in your `loader`/`action` then it's an expected flow that is handled by your code. If you also wish to log, or send those to an external service, that should be done at the time you throw the response.

## `.server` modules

While not strictly necessary, `.server` modules are a good way to explicitly mark entire modules as server-only.
The build will fail if any code in a `.server` file or `.server` directory accidentally ends up in the client module graph.

```txt
app
├── .server 👈 marks all files in this directory as server-only
│ ├── auth.ts
│ └── db.ts
├── cms.server.ts 👈 marks this file as server-only
├── root.tsx
└── routes.ts
```

`.server` modules must be within your app directory.

Refer to the Route Module section in the sidebar for more information.

## `.client` modules

While uncommon, you may have a file or dependency that uses module side effects in the browser. You can use `*.client.ts` on file names or nest files within `.client` directories to force them out of server bundles.

```ts filename=feature-check.client.ts
// this would break the server
export const supportsVibrationAPI =
"vibrate" in window.navigator;
```

Note that values exported from this module will all be `undefined` on the server, so the only places to use them are in [`useEffect`][use_effect] and user events like click handlers.

```ts
import { supportsVibrationAPI } from "./feature-check.client.ts";

console.log(supportsVibrationAPI);
// server: undefined
// client: true | false
```

[react-router-config]: https://api.reactrouter.com/v7/types/_react_router_dev.config.Config.html
[route-module]: ../start/framework/route-module
[routing]: ../start/framework/routing
Expand All @@ -316,3 +355,4 @@ Note that this does not handle thrown `Response` instances from your `loader`/`a
[rendertoreadablestream]: https://react.dev/reference/react-dom/server/renderToReadableStream
[node-streaming-entry-server]: https://github.com/remix-run/react-router/blob/dev/packages/react-router-dev/config/defaults/entry.server.node.tsx
[streaming]: ../how-to/suspense
[use_effect]: https://react.dev/reference/react/useEffect
2 changes: 1 addition & 1 deletion docs/how-to/file-route-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ If you want one of the special characters used for these route conventions to ac
| `app/routes/weird-url.[_index].tsx` | `/weird-url/_index` |
| `app/routes/dolla-bills-[$].tsx` | `/dolla-bills-$` |
| `app/routes/[[so-weird]].tsx` | `/[so-weird]` |
| `app/routes/reports.$id[.pdf].ts | `/reports/123.pdf |
| `app/routes/reports.$id[.pdf].ts` | `/reports/123.pdf` |

## Folders for Organization

Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/index.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
title: How-Tos
order: 3
order: 4
---
2 changes: 1 addition & 1 deletion docs/how-to/resource-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export function loader(_: Route.LoaderArgs) {
return Response.json({ message: "I handle GET" });
}

export function action(_: Route.LoaderArgs) {
export function action(_: Route.ActionArgs) {
return Response.json({
message: "I handle everything else",
});
Expand Down
35 changes: 11 additions & 24 deletions docs/how-to/route-module-type-safety.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,38 +53,25 @@ When auto-importing the `Route` type helper, TypeScript will generate:
import { Route } from "./+types/my-route";
```

This will work, but you may want the `type` modifier for the import added automatically as well.
But if you enable [verbatimModuleSyntax](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax):

```ts filename=app/routes/my-route.tsx
import type { Route } from "./+types/my-route";
// ^^^^
```

For example, this helps tools like bundlers to detect type-only module that can be safely excluded from the bundle.

### VSCode

In VSCode, you can get this behavior automatically by selecting `TypeScript › Preferences: Prefer Type Only Auto Imports` from the command palette or by manually setting `preferTypeOnlyAutoImports`:

```json filename=.vscode/settings.json
```json filename=tsconfig.json
{
"typescript.preferences.preferTypeOnlyAutoImports": true
"compilerOptions": {
"verbatimModuleSyntax": true
}
}
```

### eslint

In eslint, you can get this behavior by setting `prefer: "type-imports"` for the `consistent-type-imports` rule:
Then, you will get the `type` modifier for the import automatically as well:

```json
{
"@typescript-eslint/consistent-type-imports": [
"warn",
{ "prefer": "type-imports" }
]
}
```ts filename=app/routes/my-route.tsx
import type { Route } from "./+types/my-route";
// ^^^^
```

This helps tools like bundlers to detect type-only module that can be safely excluded from the bundle.

## Conclusion

React Router's Vite plugin should be automatically generating types into `.react-router/types/` anytime you edit your route config (`routes.ts`).
Expand Down
4 changes: 2 additions & 2 deletions docs/how-to/suspense.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import type { Route } from "./+types/my-route";
export async function loader({}: Route.LoaderArgs) {
// note this is NOT awaited
let nonCriticalData = new Promise((res) =>
setTimeout(() => "non-critical", 5000)
setTimeout(() => res("non-critical"), 5000)
);

let criticalData = await new Promise((res) =>
setTimeout(() => "critical", 300)
setTimeout(() => res("critical"), 300)
);

return { nonCriticalData, criticalData };
Expand Down
11 changes: 11 additions & 0 deletions docs/start/framework/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ order: 1

# Installation

<docs-info>

React Router v7 requires the following minimum versions:

- `node@20`
- `react@18`
- `react-dom@18`

</docs-info>

Most projects start with a template. Let's use a basic template maintained by React Router:
Most projects start with a template. Let's use a basic template maintained by React Router:

```shellscript nonumber
Expand Down
19 changes: 18 additions & 1 deletion docs/start/framework/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,23 @@ export default [
] satisfies RouteConfig;
```

To see `projects/home.tsx` appear in the layout, we'll need an outlet:

```tsx filename=./projects/project-layout.tsx lines=[8]
import { Outlet } from "react-router";

export default function ProjectLayout() {
return (
<div>
<aside>Example sidebar</aside>
<main>
<Outlet />
</main>
</div>
);
}
```

## Index Routes

```ts
Expand Down Expand Up @@ -308,4 +325,4 @@ Note that these routes do not participate in data loading, actions, code splitti
Next: [Route Module](./route-module)

[file-route-conventions]: ../../how-to/file-route-conventions
[outlet]: ../../api/react-router/Outlet
[outlet]: https://api.reactrouter.com/v7/functions/react_router.Outlet.html
17 changes: 10 additions & 7 deletions docs/start/framework/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ We can test this component with `createRoutesStub`. It takes an array of objects

```tsx
import { createRoutesStub } from "react-router";
import * as Test from "@testing-library/react";
import {
render,
screen,
waitFor,
} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { LoginForm } from "./LoginForm";

test("LoginForm renders error messages", async () => {
Expand All @@ -59,13 +64,11 @@ test("LoginForm renders error messages", async () => {
]);

// render the app stub at "/login"
Test.render(<Stub initialEntries={["/login"]} />);
render(<Stub initialEntries={["/login"]} />);

// simulate interactions
Test.user.click(screen.getByText("Login"));
await Test.waitFor(() => screen.findByText(USER_MESSAGE));
await Test.waitFor(() =>
screen.findByText(PASSWORD_MESSAGE)
);
userEvent.click(screen.getByText("Login"));
await waitFor(() => screen.findByText(USER_MESSAGE));
await waitFor(() => screen.findByText(PASSWORD_MESSAGE));
});
```
10 changes: 10 additions & 0 deletions docs/start/library/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ order: 1

# Installation

<docs-info>

React Router v7 requires the following minimum versions:

- `node@20`
- `react@18`
- `react-dom@18`

</docs-info>

You can start with a React template from Vite and choose "React", otherwise bootstrap your application however you prefer.

```shellscript nonumber
Expand Down
Loading

0 comments on commit 329fc0a

Please sign in to comment.