Skip to content

Commit 7fd797a

Browse files
committed
Docs: add note on data to loaders/action docs
1 parent 8360bc6 commit 7fd797a

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

docs/start/actions.md

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Client actions only run in the browser and take priority over a server action wh
1717
// route('/projects/:projectId', './project.tsx')
1818
import type * as Route from "./+types.project";
1919
import { Form } from "react-router";
20+
import { someApi } from "./api";
2021

2122
export async function clientAction({
2223
request,
@@ -53,13 +54,14 @@ Server actions only run on the server and are removed from client bundles.
5354
// route('/projects/:projectId', './project.tsx')
5455
import type * as Route from "./+types.project";
5556
import { Form } from "react-router";
57+
import { fakeDb } from "../db";
5658

5759
export async function action({
5860
request,
5961
}: Route.ActionArgs) {
6062
let formData = await request.formData();
6163
let title = await formData.get("title");
62-
let project = await someApi.updateProject({ title });
64+
let project = await fakeDb.updateProject({ title });
6365
return project;
6466
}
6567

@@ -81,6 +83,38 @@ export default function Project({
8183
}
8284
```
8385

86+
### Custom Status Codes and Headers
87+
88+
If you need to return a custom HTTP status code or custom headers from your `action`, you can do so using the [`data`][data] utility:
89+
90+
```tsx filename=app/project.tsx lines=[3,11-14,19]
91+
// route('/projects/:projectId', './project.tsx')
92+
import type * as Route from "./+types.project";
93+
import { data } from "react-router";
94+
import { fakeDb } from "../db";
95+
96+
export async function action({
97+
request,
98+
}: Route.ActionArgs) {
99+
let formData = await request.formData();
100+
let title = await formData.get("title");
101+
if (!title) {
102+
throw data(
103+
{ message: "Invalid title" },
104+
{ status: 400 }
105+
);
106+
}
107+
108+
if (!projectExists(title)) {
109+
let project = await fakeDb.createProject({ title });
110+
return data(project, { status: 201 });
111+
} else {
112+
let project = await fakeDb.updateProject({ title });
113+
return project;
114+
}
115+
}
116+
```
117+
84118
## Calling Actions
85119

86120
Actions are called declaratively through `<Form>` and imperatively through `useSubmit` (or `<fetcher.Form>` and `fetcher.submit`) by referencing the route's path and a "post" method.
@@ -159,4 +193,7 @@ fetcher.submit(
159193
);
160194
```
161195

162-
See the [Using Fetchers](../misc/fetchers) guide for more information.
196+
See the [Using Fetchers][fetchers] guide for more information.
197+
198+
[fetchers]: ../misc/fetchers
199+
[data]: ../../api/react-router/data

docs/start/data-loading.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,35 @@ export default function Product({
6565

6666
Note that the `loader` function is removed from client bundles so you can use server only APIs without worrying about them being included in the browser.
6767

68+
### Custom Status Codes and Headers
69+
70+
If you need to return a custom HTTP status code or custom headers from your `loader`, you can do so using the [`data`][data] utility:
71+
72+
```tsx filename=app/product.tsx lines=[3,6-8,14,17-21]
73+
// route("products/:pid", "./product.tsx");
74+
import type * as Route from "./+types.product";
75+
import { data } from "react-router";
76+
import { fakeDb } from "../db";
77+
78+
export function headers({ loaderHeaders }: HeadersArgs) {
79+
return loaderHeaders;
80+
}
81+
82+
export async function loader({ params }: Route.LoaderArgs) {
83+
const product = await fakeDb.getProduct(params.pid);
84+
85+
if (!product) {
86+
throw data(null, { status: 404 });
87+
}
88+
89+
return data(product, {
90+
headers: {
91+
"Cache-Control": "public; max-age=300",
92+
},
93+
});
94+
}
95+
```
96+
6897
## Static Data Loading
6998

7099
When pre-rendering, loaders are used to fetch data during the production build.
@@ -195,3 +224,4 @@ export async function Product({ id }: { id: string }) {
195224
```
196225

197226
[advanced_data_fetching]: ../tutorials/advanced-data-fetching
227+
[data]: ../../api/react-router/data

0 commit comments

Comments
 (0)