Skip to content

Commit e878b8d

Browse files
committed
Merge branch 'dev' into markdalgleish/lazy-middleware
2 parents 3720e54 + 4f885c4 commit e878b8d

File tree

101 files changed

+3575
-22
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+3575
-22
lines changed

.changeset/cuddly-dots-hear.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-router/dev": patch
3+
---
4+
5+
When `future.unstable_splitRouteModules` is set to `"enforce"`, allow both splittable and unsplittable root route exports since it's always in a single chunk.

.changeset/few-months-begin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-router": patch
3+
---
4+
5+
Fix `RequestHandler` `loadContext` parameter type when middleware is enabled

.changeset/unlucky-pumas-buy.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-router": patch
3+
---
4+
5+
[UNSTABLE] Update `Route.unstable_MiddlewareFunction` to have a return value of `Response | undefined` instead of `Response | void` becaue you should not return anything if you aren't returning the `Response`

docs/api/components/Await.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
---
2+
title: Await
3+
---
4+
5+
# Await
6+
7+
[MODES: framework, data]
8+
9+
## Summary
10+
11+
[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react_router.Await.html)
12+
13+
Used to render promise values with automatic error handling.
14+
15+
```tsx
16+
import { Await, useLoaderData } from "react-router";
17+
18+
export function loader() {
19+
// not awaited
20+
const reviews = getReviews();
21+
// awaited (blocks the transition)
22+
const book = await fetch("/api/book").then((res) =>
23+
res.json()
24+
);
25+
return { book, reviews };
26+
}
27+
28+
function Book() {
29+
const { book, reviews } = useLoaderData();
30+
return (
31+
<div>
32+
<h1>{book.title}</h1>
33+
<p>{book.description}</p>
34+
<React.Suspense fallback={<ReviewsSkeleton />}>
35+
<Await
36+
resolve={reviews}
37+
errorElement={
38+
<div>Could not load reviews 😬</div>
39+
}
40+
children={(resolvedReviews) => (
41+
<Reviews items={resolvedReviews} />
42+
)}
43+
/>
44+
</React.Suspense>
45+
</div>
46+
);
47+
}
48+
```
49+
50+
`<Await>` expects to be rendered inside of a `<React.Suspense>`
51+
52+
## Props
53+
54+
### children
55+
56+
[modes: framework, data]
57+
58+
When using a function, the resolved value is provided as the parameter.
59+
60+
```tsx [2]
61+
<Await resolve={reviewsPromise}>
62+
{(resolvedReviews) => <Reviews items={resolvedReviews} />}
63+
</Await>
64+
```
65+
66+
When using React elements, [useAsyncValue](../hooks/useAsyncValue) will provide the
67+
resolved value:
68+
69+
```tsx [2]
70+
<Await resolve={reviewsPromise}>
71+
<Reviews />
72+
</Await>;
73+
74+
function Reviews() {
75+
const resolvedReviews = useAsyncValue();
76+
return <div>...</div>;
77+
}
78+
```
79+
80+
### errorElement
81+
82+
[modes: framework, data]
83+
84+
The error element renders instead of the children when the promise rejects.
85+
86+
```tsx
87+
<Await
88+
errorElement={<div>Oops</div>}
89+
resolve={reviewsPromise}
90+
>
91+
<Reviews />
92+
</Await>
93+
```
94+
95+
To provide a more contextual error, you can use the [useAsyncError](../hooks/useAsyncError) in a
96+
child component
97+
98+
```tsx
99+
<Await
100+
errorElement={<ReviewsError />}
101+
resolve={reviewsPromise}
102+
>
103+
<Reviews />
104+
</Await>;
105+
106+
function ReviewsError() {
107+
const error = useAsyncError();
108+
return <div>Error loading reviews: {error.message}</div>;
109+
}
110+
```
111+
112+
If you do not provide an errorElement, the rejected value will bubble up to
113+
the nearest route-level ErrorBoundary and be accessible
114+
via [useRouteError](../hooks/useRouteError) hook.
115+
116+
### resolve
117+
118+
[modes: framework, data]
119+
120+
Takes a promise returned from a [LoaderFunction](../Other/LoaderFunction) value to be resolved and rendered.
121+
122+
```jsx
123+
import { useLoaderData, Await } from "react-router";
124+
125+
export async function loader() {
126+
let reviews = getReviews(); // not awaited
127+
let book = await getBook();
128+
return {
129+
book,
130+
reviews, // this is a promise
131+
};
132+
}
133+
134+
export default function Book() {
135+
const {
136+
book,
137+
reviews, // this is the same promise
138+
} = useLoaderData();
139+
140+
return (
141+
<div>
142+
<h1>{book.title}</h1>
143+
<p>{book.description}</p>
144+
<React.Suspense fallback={<ReviewsSkeleton />}>
145+
<Await
146+
// and is the promise we pass to Await
147+
resolve={reviews}
148+
>
149+
<Reviews />
150+
</Await>
151+
</React.Suspense>
152+
</div>
153+
);
154+
}
155+
```

docs/api/components/Form.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
---
2+
title: Form
3+
---
4+
5+
# Form
6+
7+
[MODES: framework, data]
8+
9+
## Summary
10+
11+
[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react_router.Form.html)
12+
13+
A progressively enhanced HTML [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form) that submits data to actions via `fetch`, activating pending states in `useNavigation` which enables advanced user interfaces beyond a basic HTML form. After a form's action completes, all data on the page is automatically revalidated to keep the UI in sync with the data.
14+
15+
Because it uses the HTML form API, server rendered pages are interactive at a basic level before JavaScript loads. Instead of React Router managing the submission, the browser manages the submission as well as the pending states (like the spinning favicon). After JavaScript loads, React Router takes over enabling web application user experiences.
16+
17+
Form is most useful for submissions that should also change the URL or otherwise add an entry to the browser history stack. For forms that shouldn't manipulate the browser history stack, use [`<fetcher.Form>`][fetcher_form].
18+
19+
```tsx
20+
import { Form } from "react-router";
21+
22+
function NewEvent() {
23+
return (
24+
<Form action="/events" method="post">
25+
<input name="title" type="text" />
26+
<input name="description" type="text" />
27+
</Form>
28+
);
29+
}
30+
```
31+
32+
## Props
33+
34+
### action
35+
36+
[modes: framework, data]
37+
38+
The URL to submit the form data to. If `undefined`, this defaults to the closest route in context.
39+
40+
### discover
41+
42+
[modes: framework, data]
43+
44+
Determines application manifest discovery behavior.
45+
46+
### encType
47+
48+
[modes: framework, data]
49+
50+
The encoding type to use for the form submission.
51+
52+
### fetcherKey
53+
54+
[modes: framework, data]
55+
56+
Indicates a specific fetcherKey to use when using `navigate={false}` so you
57+
can pick up the fetcher's state in a different component in a [useFetcher](../hooks/useFetcher).
58+
59+
### method
60+
61+
[modes: framework, data]
62+
63+
The HTTP verb to use when the form is submitted. Supports "get", "post",
64+
"put", "delete", and "patch".
65+
66+
Native `<form>` only supports `get` and `post`, avoid the other verbs if
67+
you'd like to support progressive enhancement
68+
69+
### navigate
70+
71+
[modes: framework, data]
72+
73+
Skips the navigation and uses a [useFetcher](../hooks/useFetcher) internally
74+
when `false`. This is essentially a shorthand for `useFetcher()` +
75+
`<fetcher.Form>` where you don't care about the resulting data in this
76+
component.
77+
78+
### onSubmit
79+
80+
[modes: framework, data]
81+
82+
A function to call when the form is submitted. If you call
83+
`event.preventDefault()` then this form will not do anything.
84+
85+
### preventScrollReset
86+
87+
[modes: framework, data]
88+
89+
Prevent the scroll position from resetting to the top of the viewport on
90+
completion of the navigation when using the <ScrollRestoration> component
91+
92+
### relative
93+
94+
[modes: framework, data]
95+
96+
Determines whether the form action is relative to the route hierarchy or
97+
the pathname. Use this if you want to opt out of navigating the route
98+
hierarchy and want to instead route based on /-delimited URL segments
99+
100+
### reloadDocument
101+
102+
[modes: framework, data]
103+
104+
Forces a full document navigation instead of client side routing + data
105+
fetch.
106+
107+
### replace
108+
109+
[modes: framework, data]
110+
111+
Replaces the current entry in the browser history stack when the form
112+
navigates. Use this if you don't want the user to be able to click "back"
113+
to the page with the form on it.
114+
115+
### state
116+
117+
[modes: framework, data]
118+
119+
State object to add to the history stack entry for this navigation
120+
121+
### viewTransition
122+
123+
[modes: framework, data]
124+
125+
Enables a [View
126+
Transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)
127+
for this navigation. To apply specific styles during the transition see
128+
[useViewTransitionState](../hooks/useViewTransitionState).

0 commit comments

Comments
 (0)