Skip to content

Commit bf85c4b

Browse files
committed
Merge branch 'release-next'
2 parents a23f017 + 667f936 commit bf85c4b

Some content is hidden

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

46 files changed

+18944
-17404
lines changed

contributors.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
- ianflynnwork
8989
- IbraRouisDev
9090
- igniscyan
91+
- imjordanxd
9192
- infoxicator
9293
- IsaiStormBlesed
9394
- Isammoc

docs/components/form.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ interface FormProps
2020
| "text/plain";
2121
action?: string;
2222
onSubmit?: React.FormEventHandler<HTMLFormElement>;
23+
fetcherKey?: string;
24+
navigate?: boolean;
2325
preventScrollReset?: boolean;
2426
relative?: "route" | "path";
2527
reloadDocument?: boolean;
@@ -197,6 +199,14 @@ function Project() {
197199

198200
As you can see, both forms submit to the same route but you can use the `request.method` to branch on what you intend to do. After the actions completes, the `loader` will be revalidated and the UI will automatically synchronize with the new data.
199201

202+
## `navigate`
203+
204+
You can tell the form to skip the navigation and use a [fetcher][usefetcher] internally by specifying `<Form navigate={false}>`. This is essentially a shorthand for `useFetcher()` + `<fetcher.Form>` where you don't care about the resulting data and only want to kick off a submission and access the pending state via [`useFetchers()`][usefetchers].
205+
206+
## `fetcherKey`
207+
208+
When using a non-navigating `Form`, you may also optionally specify your own fetcher key to use via `<Form navigate={false} fetcherKey="my-key">`.
209+
200210
## `replace`
201211

202212
Instructs the form to replace the current entry in the history stack, instead of pushing the new entry.
@@ -367,6 +377,7 @@ You can access those values from the `request.url`
367377
[useactiondata]: ../hooks/use-action-data
368378
[formdata]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
369379
[usefetcher]: ../hooks/use-fetcher
380+
[usefetchers]: ../hooks/use-fetchers
370381
[htmlform]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
371382
[htmlformaction]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-action
372383
[htmlform-method]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-method

docs/guides/api-development-strategy.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ const router = createBrowserRouter(routes, {
6565

6666
| Flag | Description |
6767
| ------------------------ | --------------------------------------------------------------------- |
68+
| `v7_fetcherPersist` | Delay active fetcher cleanup until they return to an `idle` state |
6869
| `v7_normalizeFormMethod` | Normalize `useNavigation().formMethod` to be an uppercase HTTP Method |
70+
| `v7_prependBasename` | Prepend the router basename to navigate/fetch paths |
6971

7072
### React Router Future Flags
7173

docs/hooks/use-fetcher.md

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,37 @@ Fetchers have a lot of built-in behavior:
6060
- Handles uncaught errors by rendering the nearest `errorElement` (just like a normal navigation from `<Link>` or `<Form>`)
6161
- Will redirect the app if your action/loader being called returns a redirect (just like a normal navigation from `<Link>` or `<Form>`)
6262

63-
## `fetcher.state`
63+
## Options
6464

65-
You can know the state of the fetcher with `fetcher.state`. It will be one of:
65+
### `key`
6666

67-
- **idle** - nothing is being fetched.
68-
- **submitting** - A route action is being called due to a fetcher submission using POST, PUT, PATCH, or DELETE
69-
- **loading** - The fetcher is calling a loader (from a `fetcher.load`) or is being revalidated after a separate submission or `useRevalidator` call
67+
By default, `useFetcher` generate a unique fetcher scoped to that component (however, it may be looked up in [`useFetchers()`][use-fetchers] while in-flight). If you want to identify a fetcher with your own `key` such that you can access it from elsewhere in your app, you can do that with the `key` option:
68+
69+
```tsx lines=[2,8]
70+
function AddToBagButton() {
71+
const fetcher = useFetcher({ key: "add-to-bag" });
72+
return <fetcher.Form method="post">...</fetcher.Form>;
73+
}
74+
75+
// Then, up in the header...
76+
function CartCount({ count }) {
77+
const fetcher = useFetcher({ key: "add-to-bag" });
78+
const inFlightCount = Number(
79+
fetcher.formData?.get("quantity") || 0
80+
);
81+
const optimisticCount = count + inFlightCount;
82+
return (
83+
<>
84+
<BagIcon />
85+
<span>{optimisticCount}</span>
86+
</>
87+
);
88+
}
89+
```
90+
91+
## Components
7092

71-
## `fetcher.Form`
93+
### `fetcher.Form`
7294

7395
Just like `<Form>` except it doesn't cause a navigation. <small>(You'll get over the dot in JSX ... we hope!)</small>
7496

@@ -83,6 +105,8 @@ function SomeComponent() {
83105
}
84106
```
85107

108+
## Methods
109+
86110
## `fetcher.load()`
87111

88112
Loads data from a route loader.
@@ -140,7 +164,17 @@ If you want to submit to an index route, use the [`?index` param][indexsearchpar
140164

141165
If you find yourself calling this function inside of click handlers, you can probably simplify your code by using `<fetcher.Form>` instead.
142166

143-
## `fetcher.data`
167+
## Properties
168+
169+
### `fetcher.state`
170+
171+
You can know the state of the fetcher with `fetcher.state`. It will be one of:
172+
173+
- **idle** - nothing is being fetched.
174+
- **submitting** - A route action is being called due to a fetcher submission using POST, PUT, PATCH, or DELETE
175+
- **loading** - The fetcher is calling a loader (from a `fetcher.load`) or is being revalidated after a separate submission or `useRevalidator` call
176+
177+
### `fetcher.data`
144178

145179
The returned data from the loader or action is stored here. Once the data is set, it persists on the fetcher even through reloads and resubmissions.
146180

@@ -171,7 +205,7 @@ function ProductDetails({ product }) {
171205
}
172206
```
173207

174-
## `fetcher.formData`
208+
### `fetcher.formData`
175209

176210
When using `<fetcher.Form>` or `fetcher.submit()`, the form data is available to build optimistic UI.
177211

@@ -204,15 +238,15 @@ function TaskCheckbox({ task }) {
204238
}
205239
```
206240

207-
## `fetcher.json`
241+
### `fetcher.json`
208242

209243
When using `fetcher.submit(data, { formEncType: "application/json" })`, the submitted JSON is available via `fetcher.json`.
210244

211-
## `fetcher.text`
245+
### `fetcher.text`
212246

213247
When using `fetcher.submit(data, { formEncType: "text/plain" })`, the submitted text is available via `fetcher.text`.
214248

215-
## `fetcher.formAction`
249+
### `fetcher.formAction`
216250

217251
Tells you the action url the form is being submitted to.
218252

@@ -223,7 +257,7 @@ Tells you the action url the form is being submitted to.
223257
fetcher.formAction; // "mark-as-read"
224258
```
225259

226-
## `fetcher.formMethod`
260+
### `fetcher.formMethod`
227261

228262
Tells you the method of the form being submitted: get, post, put, patch, or delete.
229263

@@ -243,4 +277,5 @@ fetcher.formMethod; // "post"
243277
[link]: ../components/link
244278
[form]: ../components/form
245279
[api-development-strategy]: ../guides/api-development-strategy
246-
[use-submit]: ./use-submit.md
280+
[use-submit]: ./use-submit
281+
[use-fetchers]: ./use-fetchers

docs/hooks/use-submit.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,15 @@ submit(null, {
150150
<Form action="/logout" method="post" />;
151151
```
152152

153-
Because submissions are navigations, the options may also contain the other navigation related props from [`<Form>`][form] such as `replace`, `state`, `preventScrollReset`, `relative`, `unstable_viewTransition` etc.
153+
Because submissions are navigations, the options may also contain the other navigation related props from [`<Form>`][form] such as:
154+
155+
- `fetcherKey`
156+
- `navigate`
157+
- `preventScrollReset`
158+
- `relative`
159+
- `replace`
160+
- `state`
161+
- `unstable_viewTransition`
154162

155163
[pickingarouter]: ../routers/picking-a-router
156164
[form]: ../components/form

docs/routers/create-browser-router.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,22 @@ const router = createBrowserRouter(routes, {
114114
});
115115
```
116116

117+
The following future flags are currently available:
118+
119+
| Flag | Description |
120+
| ------------------------ | --------------------------------------------------------------------- |
121+
| `v7_fetcherPersist` | Delay active fetcher cleanup until they return to an `idle` state |
122+
| `v7_normalizeFormMethod` | Normalize `useNavigation().formMethod` to be an uppercase HTTP Method |
123+
| `v7_prependBasename` | Prepend the router basename to navigate/fetch paths |
124+
117125
## `window`
118126

119127
Useful for environments like browser devtool plugins or testing to use a different window than the global `window`.
120128

121129
[loader]: ../route/loader
122130
[action]: ../route/action
123131
[fetcher]: ../hooks/use-fetcher
124-
[browser-router]: ./browser-router
125-
[form]: ../components/form
126132
[route]: ../route/route
127-
[routes]: ../components/routes
128133
[historyapi]: https://developer.mozilla.org/en-US/docs/Web/API/History
129134
[api-development-strategy]: ../guides/api-development-strategy
130135
[remixing-react-router]: https://remix.run/blog/remixing-react-router

0 commit comments

Comments
 (0)