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/route/action.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
@@ -6,7 +6,7 @@ title: action
6
6
7
7
<docs-success>Watch the <ahref="https://www.youtube.com/playlist?list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">📼 Remix Singles</a>: <ahref="https://www.youtube.com/watch?v=Iv25HAHaFDs&list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">Data Mutations with Form + action</a> and <ahref="https://www.youtube.com/watch?v=w2i-9cYxSdc&list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">Multiple Forms and Single Button Mutations</a></docs-success>
8
8
9
-
A route `action` is a serveronly function to handle data mutations and other actions. If a non-`GET` request is made to your route (`DELETE`, `PATCH`, `POST`, or `PUT`) then the action is called before the [`loader`][loader]s.
9
+
A route `action` is a server-only function to handle data mutations and other actions. If a non-`GET` request is made to your route (`DELETE`, `PATCH`, `POST`, or `PUT`) then the action is called before the [`loader`][loader]s.
10
10
11
11
`action`s have the same API as `loader`s, the only difference is when they are called. This enables you to co-locate everything about a data set in a single route module: the data read, the component that renders the data, and the data writes:
12
12
@@ -57,7 +57,7 @@ If you want to post to an index route use `?index` in the action: `<Form action=
Also note that forms without an action prop (`<Form method="post">`) will automatically post to the same route within which they are rendered, so using the `?index` param to disambiguate between parent and index routes is only useful if you're posting to an index route from somewhere besides the index route itself. If you're posting from the index route to itself, or from the parent route to itself, you don't need to define a `<Form action>` at all, just omit it: `<Form method="post">`.
60
+
Also note that forms without an action prop (`<Form method="post">`) will automatically post to the same route within which they are rendered, so using the `?index` param to disambiguate between parent and index routes is only useful if you're posting to an index route from somewhere besides the index route itself. If you're posting from the index route to itself, or from the parent route to itself, you don't need to define a `<Form action>` at all, omit it: `<Form method="post">`.
This function is only ever run on the client, and can be used in a few ways:
26
+
This function is only ever run on the client and can be used in a few ways:
27
27
28
28
- Instead of a server `loader` for full-client routes
29
29
- To use alongside a `clientLoader` cache by invalidating the cache on mutations
@@ -58,7 +58,7 @@ export default function Component() {
58
58
59
59
### `clientLoader.hydrate`
60
60
61
-
If you need to run your `clientLoader` during hydration on the initial document request, you can opt-in by setting `clientLoader.hydrate=true`. This will tell Remix that it needs to run the `clientLoader` on hydration. Without a `HydrateFallback`, your route component will be SSR'd with the server `loader` data - and then `clientLoader` will run and the returned data will be updated in-place in the hydrated route Component.
61
+
If you need to run your `clientLoader` during hydration on the initial document request, you can optin by setting `clientLoader.hydrate=true`. This will tell Remix that it needs to run the `clientLoader` on hydration. Without a `HydrateFallback`, your route component will be SSR'd with the server `loader` data - and then `clientLoader` will run and the returned data will be updated in-place in the hydrated route Component.
62
62
63
63
<docs-info>If a route exports a `clientLoader` and does not export a server `loader`, then `clientLoader.hydrate` is automatically treated as `true` since there is no server data to SSR with. Therefore, we always need to run the `clientLoader` on hydration before rendering the route component.</docs-info>
64
64
@@ -78,7 +78,7 @@ This function receives the same [`request`][loader-request] argument as a [`load
78
78
79
79
### `serverLoader`
80
80
81
-
`serverLoader` is an asynchronous function to get the data from the server `loader` for this route. On client-side navigations, this will make a [fetch][fetch] call to the Remix server `loader`. If you opt-into running your `clientLoader` on hydration, then this function will return you the data that was already loaded on the server (via `Promise.resolve`).
81
+
`serverLoader` is an asynchronous function to get the data from the server `loader` for this route. On client-side navigations, this will make a [fetch][fetch] call to the Remix server `loader`. If you opt-into running your `clientLoader` on hydration, then this function will return you the data already loaded on the server (via `Promise.resolve`).
Copy file name to clipboardExpand all lines: docs/route/error-boundary.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
@@ -4,7 +4,7 @@ title: ErrorBoundary
4
4
5
5
# `ErrorBoundary`
6
6
7
-
A Remix `ErrorBoundary` component works just like normal React [error boundaries][error-boundaries], but with a few extra capabilities. When there is an error in your route component, the `ErrorBoundary` will be rendered in its place, nested inside any parent routes. `ErrorBoundary` components also render when there is an error in the `loader` or `action` functions for a route, so all errors for that route may be handled in one spot.
7
+
A Remix `ErrorBoundary` component works just like normal React [error boundaries][error-boundaries] but with a few extra capabilities. When there is an error in your route component, the `ErrorBoundary` will be rendered in its place, nested inside any parent routes. `ErrorBoundary` components also render when there is an error in the `loader` or `action` functions for a route, so all errors for that route may be handled in one spot.
8
8
9
9
The most common use-cases tend to be:
10
10
@@ -14,7 +14,7 @@ The most common use-cases tend to be:
14
14
- Throwing a 404 when you can't find requested data
15
15
- React may unintentionally throw an `Error` if it encounters a runtime error during rendering
16
16
17
-
To obtain the thrown object, you can use the [`useRouteError`][use-route-error] hook. When a `Response` is thrown, it will be automatically unwrapped into an `ErrorResponse` instance with `state`/`statusText`/`data` fields so that you don't need to bother with `await response.json()` in your component. To differentiate thrown `Response`'s from thrown `Error`'s you can use the [`isRouteErrorResponse`][is-route-error-response] utility.
17
+
To get the thrown object, you can use the [`useRouteError`][use-route-error] hook. When a `Response` is thrown, it will be automatically unwrapped into an `ErrorResponse` instance with `state`/`statusText`/`data` fields so that you don't need to bother with `await response.json()` in your component. To differentiate thrown `Response`'s from thrown `Error`'s you can use the [`isRouteErrorResponse`][is-route-error-response] utility.
Copy file name to clipboardExpand all lines: docs/route/headers.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -58,11 +58,11 @@ If we are looking at `/users/123/profile` then three routes are rendering:
58
58
59
59
If a user is looking at `/users/123/profile` and `users.$userId.profile.tsx` does not export a `headers` function, then Remix will use the return value of `users.$userId.tsx`'s `headers` function. If that file doesn't export one, then it will use the result of the one in `users.tsx`, and so on.
60
60
61
-
If all three define `headers`, the deepest module wins, in this case `users.$userId.profile.tsx`. However, if your `users.$userId.profile.tsx`'s `loader` threw and bubbled to a boundary in `users.$userId.tsx` - then `users.$userId.tsx`'s `headers` function would be used as it is the leafrendered route.
61
+
If all three define `headers`, the deepest module wins, in this case `users.$userId.profile.tsx`. However, if your `users.$userId.profile.tsx`'s `loader` threw and bubbled to a boundary in `users.$userId.tsx` - then `users.$userId.tsx`'s `headers` function would be used as it is the leaf-rendered route.
62
62
63
63
We don't want surprise headers in your responses, so it's your job to merge them if you'd like. Remix passes in the `parentHeaders` to your `headers` function. So `users.tsx` headers get passed to `users.$userId.tsx`, and then `users.$userId.tsx`'s `headers` are passed to `users.$userId.profile.tsx`'s `headers`.
64
64
65
-
That is all to say that Remix has given you a very large gun with which to shoot your foot. You need to be careful not to send a `Cache-Control` from a child route module that is more aggressive than a parent route. Here's some code that picks the least aggressive caching in these cases:
65
+
That is all to say that Remix has given you a huge gun with which to shoot your foot. You need to be careful not to send a `Cache-Control` from a child route module that is more aggressive than a parent route. Here's some code that picks the least aggressive caching in these cases:
66
66
67
67
```tsx
68
68
importtype { HeadersFunction } from"@remix-run/node"; // or cloudflare/deno
@@ -125,7 +125,7 @@ export default function handleRequest(
125
125
}
126
126
```
127
127
128
-
Just keep in mind that doing this will apply to _all_ document requests, but does not apply to `data` requests (for client-side transitions for example). For those, use [`handleDataRequest`][handle-data-request].
128
+
Keep in mind that doing this will apply to _all_ document requests, but does not apply to `data` requests (for client-side transitions, for example). For those, use [`handleDataRequest`][handle-data-request].
Copy file name to clipboardExpand all lines: docs/route/hydrate-fallback.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
@@ -6,7 +6,7 @@ title: HydrateFallback
6
6
7
7
A `HydrateFallback` component is your way of informing Remix that you do not want to render your route component until _after_ the `clientLoader` has run on hydration. When exported, Remix will render the fallback during SSR instead of your default route component, and will render your route component client-side once the `clientLoader` completes.
8
8
9
-
The most common use-cases for this are client-only routes (such an in-browser canvas game) and augmenting your server data with client-side data (such as saved user preferences).
9
+
The most common use-cases for this are client-only routes (such as an in-browser canvas game) and augmenting your server data with client-side data (such as saved user preferences).
10
10
11
11
```tsx filename=routes/client-only-route.tsx
12
12
exportasyncfunction clientLoader() {
@@ -63,7 +63,7 @@ export default function Component() {
63
63
64
64
There are a few nuances worth noting around the behavior of `HydrateFallback`:
65
65
66
-
- It is only relevant on initial document request and hydration, and will not be rendered on any subsequent client-side navigations
66
+
- It is only relevant on initial document request and hydration and will not be rendered on any subsequent client-side navigations
67
67
- It is only relevant when you are also setting [`clientLoader.hydrate=true`][hydrate-true] on a given route
68
68
- It is also relevant if you do have a `clientLoader` without a server `loader`, as this implies `clientLoader.hydrate=true` since there is otherwise no loader data at all to return from `useLoaderData`
69
69
- Even if you do not specify a `HydrateFallback` in this case, Remix will not render your route component and will bubble up to any ancestor `HydrateFallback` component
This function is only ever run on the server. On the initial server render, it will provide data to the HTML document. On navigations in the browser, Remix will call the function via [`fetch`][fetch] from the browser.
20
20
21
-
This means you can talk directly to your database, use server-only API secrets, etc. Any code that isn't used to render the UI will be removed from the browser bundle.
21
+
This means you can talk directly to your database, use server-only API secrets, etc. Any code not used to render the UI will be removed from the browser bundle.
22
22
23
23
Using the database ORM [Prisma][prisma] as an example:
Because multiple nested routes render at the same time, there is some merging that needs to happen to determine the meta tags that ultimately render. Remix gives you complete control over this merge because there is no obvious default.
152
152
153
-
Remix will take the last matching route with a meta export and use that. This allows you to override things like `title`, remove things like `og:image` that the parent route added, or keep everything from the parent and add new meta for the child route.
153
+
Remix will take the last matching route with a `meta` export and use that. This allows you to override things like `title`, remove things like `og:image` that the parent route added, or keep everything from the parent and add new meta for the child route.
154
154
155
155
This can get quite tricky when you're new.
156
156
@@ -186,7 +186,7 @@ With this code, we will lose the `viewport` meta tag at `/projects` and `/projec
186
186
187
187
### Global `meta`
188
188
189
-
Nearly every app will have global meta like the `viewport` and `charSet`. We recommend using normal [`<meta>` tags][meta-element] inside the [root route][root-route] instead of the `meta` export, so you simply don't have to deal with merging:
189
+
Nearly every app will have global meta like the `viewport` and `charSet`. We recommend using normal [`<meta>` tags][meta-element] inside the [root route][root-route] instead of the `meta` export, so you don't have to deal with merging:
<docs-warning>This feature is an <i>additional</i> optimization. In general, Remix's design already optimizes which loaders need to be called and when. When you use this feature you risk your UI getting out of sync with your server. Use with caution!</docs-warning>
28
+
<docs-warning>This feature is an <i>additional</i> optimization. In general, Remix's design already optimizes which loaders need to be called and when. When you use this feature, you risk your UI getting out of sync with your server. Use with caution!</docs-warning>
29
29
30
30
During client-side transitions, Remix will optimize reloading of routes that are already rendering, like not reloading layout routes that aren't changing. In other cases, like form submissions or search param changes, Remix doesn't know which routes need to be reloaded, so it reloads them all to be safe. This ensures your UI always stays in sync with the state on your server.
31
31
@@ -35,7 +35,7 @@ This function lets apps further optimize by returning `false` when Remix is abou
35
35
36
36
## `actionResult`
37
37
38
-
When a submission causes the revalidation this will be the result of the action—either action data or an error if the action failed. It's common to include some information in the action result to instruct `shouldRevalidate` to revalidate or not.
38
+
When a submission causes the revalidation, this will be the result of the action—either action data or an error if the action failed. It's common to include some information in the action result to instruct `shouldRevalidate` to revalidate or not.
39
39
40
40
```tsx
41
41
exportasyncfunction action() {
@@ -127,7 +127,7 @@ In the case of navigation, these are the [URL params][url-params] from the next
127
127
128
128
## `nextUrl`
129
129
130
-
In the case of navigation, this the URL the user is requesting. Some revalidations are not navigation, so it will simply be the same as `currentUrl`.
130
+
In the case of navigation, this is the URL the user is requesting. Some revalidations are not navigation, so it will simply be the same as `currentUrl`.
131
131
132
132
## `formMethod`
133
133
@@ -145,7 +145,7 @@ The data submitted with the form that triggered the revalidation.
145
145
146
146
### Never reloading the root
147
147
148
-
It's common for root loaders to return data that never changes, like environment variables to be sent to the client app. In these cases you never need the root loader to be called again. For this case, you can simply `return false`.
148
+
It's common for root loaders to return data that never changes, like environment variables, to be sent to the client app. In these cases you never need the root loader to be called again. For this case, you can simply `return false`.
149
149
150
150
```tsx lines=[10]
151
151
exportconst loader =async () => {
@@ -224,7 +224,7 @@ export async function loader({
224
224
}
225
225
```
226
226
227
-
There are a lot of ways to do this, and the rest of the code in the app matters, but ideally you don't think about the UI you're trying to optimize (the search params changing) but instead look at the values your loader cares about. In our case, it only cares about the projectId, so we can check two things:
227
+
There are a lot of ways to do this. The rest of the code in the app matters, but ideally, you don't think about the UI you're trying to optimize (the search params changing) but instead look at the values your loader cares about. In our case, it only cares about the projectId, so we can check two things:
0 commit comments