You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/components/routes.md
+4-1Lines changed: 4 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,7 +17,7 @@ interface RoutesProps {
17
17
</Routes>;
18
18
```
19
19
20
-
<docs-info>If you're using a data router like [`createBrowserRouter`][createbrowserrouter] it is uncommon to use this component as it does not participate in data loading.</docs-info>
20
+
<docs-info>If you're using a data router like [`createBrowserRouter`][createbrowserrouter] it is uncommon to use this component as routes defined as part of a descendant `<Routes>` tree cannot leverage the [Data APIs][data-apis] available to [`RouterProvider`][router-provider] apps. You **can and should** use this component within your `RouterProvider` application [while you are migrating][migrating-to-router-provider].</docs-info>
21
21
22
22
Whenever the location changes, `<Routes>` looks through all its child routes to find the best match and renders that branch of the UI. `<Route>` elements may be nested to indicate nested UI, which also correspond to nested URL paths. Parent routes render their child routes by rendering an [`<Outlet>`][outlet].
23
23
@@ -38,3 +38,6 @@ Whenever the location changes, `<Routes>` looks through all its child routes to
Copy file name to clipboardExpand all lines: docs/guides/ssr.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -143,7 +143,7 @@ Once we've sent the HTML back to the browser, we'll need to "hydrate" the applic
143
143
144
144
```jsx filename=entry-client.jsx lines=[10-15]
145
145
import*asReactfrom"react";
146
-
importReactDOMfrom"react-dom/client";
146
+
import*asReactDOMfrom"react-dom/client";
147
147
import {
148
148
createBrowserRouter,
149
149
RouterProvider,
@@ -275,7 +275,7 @@ app.listen(3000);
275
275
And finally, you'll need a similar file to "hydrate" the app with your JavaScript bundle that includes the very same `App` component. Note the use of `BrowserRouter` instead of `StaticRouter`.
Copy file name to clipboardExpand all lines: docs/route/action.md
+58Lines changed: 58 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -129,6 +129,62 @@ You can `throw` in your action to break out of the current call stack (stop runn
129
129
130
130
For more details and expanded use cases, read the [errorElement][errorelement] documentation.
131
131
132
+
## Handling multiple actions per route
133
+
134
+
A fairly common question that pops up is _"What if I need to handle multiple different behaviors in my action?"_ There's a few ways to accomplish this, but usually the simplest is to put a `name`/`value` on your `<button type="submit">` and use that in the action to decide which code to execute (that's right - submitting [buttons][button] can have name/value attributes!):
135
+
136
+
```jsx lines=[3,5,10,30-32,42-44]
137
+
asyncfunctionaction({ request }) {
138
+
let formData =awaitrequest.formData();
139
+
let intent =formData.get("intent");
140
+
141
+
if (intent ==="edit") {
142
+
awaiteditSong(formData);
143
+
return { ok:true };
144
+
}
145
+
146
+
if (intent ==="add") {
147
+
awaitaddSong(formData);
148
+
return { ok:true };
149
+
}
150
+
151
+
throwjson(
152
+
{ message:"Invalid intent" },
153
+
{ status:400 }
154
+
);
155
+
}
156
+
157
+
functionComponent() {
158
+
let song =useLoaderData();
159
+
160
+
// When the song exists, show an edit form
161
+
if (song) {
162
+
return (
163
+
<Form method="post">
164
+
<p>Edit song lyrics:</p>
165
+
{/* Edit song inputs */}
166
+
<button type="submit" name="intent" value="edit">
167
+
Edit
168
+
</button>
169
+
</Form>
170
+
);
171
+
}
172
+
173
+
// Otherwise show a form to add a new song
174
+
return (
175
+
<Form method="post">
176
+
<p>Add newlyrics:</p>
177
+
{/* Add song inputs */}
178
+
<button type="submit" name="intent" value="add">
179
+
Add
180
+
</button>
181
+
</Form>
182
+
);
183
+
}
184
+
```
185
+
186
+
If a button name/value isn't right for your use case, you could also use a hidden input to send and `intent` or you could submit different HTTP methods via the [`<Form method>`][form-method] prop (`POST` for add, `PUT`/`PATCH` for edit, `DELETE` for remove).
187
+
132
188
[loader]: ./loader
133
189
[pickingarouter]: ../routers/picking-a-router
134
190
[dynamicsegments]: ./route#dynamic-segments
@@ -146,3 +202,5 @@ For more details and expanded use cases, read the [errorElement][errorelement] d
Copy file name to clipboardExpand all lines: docs/start/tutorial.md
+13-3Lines changed: 13 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -68,8 +68,8 @@ The `main.jsx` file is the entry point. Open it up and we'll put React Router on
68
68
👉 **Create and render a [browser router][createbrowserrouter] in `main.jsx`**
69
69
70
70
```jsx lines=[3-6,9-14,18] filename=src/main.jsx
71
-
importReactfrom"react";
72
-
importReactDOMfrom"react-dom/client";
71
+
import*asReactfrom"react";
72
+
import*asReactDOMfrom"react-dom/client";
73
73
import {
74
74
createBrowserRouter,
75
75
RouterProvider,
@@ -1487,10 +1487,19 @@ You could certainly do this as a controlled component, but you'll end up with mo
1487
1487
1488
1488
Notice how controlling the input requires three points of synchronization now instead of just one. The behavior is identical but the code is more complex.
0 commit comments