|
| 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]: ../api/data-routers/loader |
| 84 | +[form_element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form |
| 85 | +[form_component]: ../api/components/Form |
| 86 | +[action]: ../api/data-routers/action |
0 commit comments