| 1 | ---
|
| 2 | title: Index Query Param
|
| 3 | ---
|
| 4 |
|
| 5 | # Index Query Param
|
| 6 |
|
| 7 | [MODES: framework, data]
|
| 8 |
|
| 9 | ## Overview
|
| 10 |
|
| 11 | You may find a wild `?index` appearing in the URL of your app when submitting forms.
|
| 12 |
|
| 13 | Because of nested routes, multiple routes in your route hierarchy can match the URL. Unlike navigations where all matching route [`loader`][loader]s are called to build up the UI, when a [`form`][form_element] is submitted, _only one action is called_.
|
| 14 |
|
| 15 | Because index routes share the same URL as their parent, the `?index` param lets you disambiguate between the two.
|
| 16 |
|
| 17 | ## Understanding Index Routes
|
| 18 |
|
| 19 | For example, consider the following route structure:
|
| 20 |
|
| 21 | ```ts filename=app/routes.ts
|
| 22 | import {
|
| 23 | type RouteConfig,
|
| 24 | route,
|
| 25 | index,
|
| 26 | } from "@react-router/dev/routes";
|
| 27 |
|
| 28 | export default [
|
| 29 | route("projects", "./pages/projects.tsx", [
|
| 30 | index("./pages/projects/index.tsx"),
|
| 31 | route(":id", "./pages/projects/project.tsx"),
|
| 32 | ]),
|
| 33 | ] satisfies RouteConfig;
|
| 34 | ```
|
| 35 |
|
| 36 | This creates two routes that match `/projects`:
|
| 37 |
|
| 38 | - The parent route (`./pages/projects.tsx`)
|
| 39 | - The index route (`./pages/projects/index.tsx`)
|
| 40 |
|
| 41 | ## Form Submission Targeting
|
| 42 |
|
| 43 | For example, consider the following forms:
|
| 44 |
|
| 45 | ```tsx
|
| 46 | <Form method="post" action="/projects" />
|
| 47 | <Form method="post" action="/projects?index" />
|
| 48 | ```
|
| 49 |
|
| 50 | The `?index` param will submit to the index route; the action without the index param will submit to the parent route.
|
| 51 |
|
| 52 | When a [`<Form>`][form_component] is rendered in an index route without an [`action`][action], the `?index` param will automatically be appended so that the form posts to the index route. The following form, when submitted, will post to `/projects?index` because it is rendered in the context of the `projects` index route:
|
| 53 |
|
| 54 | ```tsx filename=app/pages/projects/index.tsx
|
| 55 | function ProjectsIndex() {
|
| 56 | return <Form method="post" />;
|
| 57 | }
|
| 58 | ```
|
| 59 |
|
| 60 | If you moved the code to the project layout (`./pages/projects.tsx` in this example), it would instead post to `/projects`.
|
| 61 |
|
| 62 | This applies to `<Form>` and all of its cousins:
|
| 63 |
|
| 64 | ```tsx
|
| 65 | function Component() {
|
| 66 | const submit = useSubmit();
|
| 67 | submit({}, { action: "/projects" });
|
| 68 | submit({}, { action: "/projects?index" });
|
| 69 | }
|
| 70 | ```
|
| 71 |
|
| 72 | ```tsx
|
| 73 | function Component() {
|
| 74 | const fetcher = useFetcher();
|
| 75 | fetcher.submit({}, { action: "/projects" });
|
| 76 | fetcher.submit({}, { action: "/projects?index" });
|
| 77 | <fetcher.Form action="/projects" />;
|
| 78 | <fetcher.Form action="/projects?index" />;
|
| 79 | <fetcher.Form />; // defaults to the route in context
|
| 80 | }
|
| 81 | ```
|
| 82 |
|
| 83 | [loader]: ../start/data/route-object#loader
|
| 84 | [form_element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
|
| 85 | [form_component]: ../api/components/Form
|
| 86 | [action]: ../start/data/route-object#action
|