Remix Loader/Action チートシート:Request/Response API 逆引き大全
Remix で Web アプリケーションを開発していると、Loader や Action で Request を処理し、Response を返す場面が頻繁に訪れます。しかし、「URL パラメータはどう取得するんだっけ?」「Cookie の設定方法は?」と、毎回調べ直していませんか?
この記事では、Remix の Loader と Action で使える Request/Response API を逆引き形式でまとめました。実務で「あ、これどうやるんだっけ?」と思った瞬間に、すぐ答えが見つかるチートシートとして活用していただけます。
Loader/Action Request API 早見表
開発中に「このデータはどう取得するの?」と迷ったら、この表をご覧ください。
| # | やりたいこと | API | 使用例 |
|---|---|---|---|
| 1 | URL パラメータを取得 | new URL(request.url).searchParams | ?page=2 → searchParams.get("page") |
| 2 | Form データを取得 | await request.formData() | formData.get("username") |
| 3 | JSON ボディを取得 | await request.json() | const data = await request.json() |
| 4 | リクエストヘッダーを取得 | request.headers.get() | request.headers.get("Authorization") |
| 5 | Cookie を取得 | request.headers.get("Cookie") | cookie.parse(request.headers.get("Cookie")) |
| 6 | リクエストメソッドを確認 | request.method | if (request.method === "POST") |
| 7 | パスパラメータを取得 | params 引数 | loader({ params }) => params.id |
| 8 | リクエスト URL 全体を取得 | request.url | const url = new URL(request.url) |
Loader/Action Response API 早見表
「このレスポンスはどう返すの?」と悩んだら、この表で即座に解決できます。
| # | やりたいこと | API | 使用例 |
|---|---|---|---|
| 1 | JSON レスポンスを返す | json() | return json({ message: "成功" }) |
| 2 | リダイレクトする | redirect() | return redirect("/dashboard") |
| 3 | ステータスコードを指定 | json(data, { status }) | return json({ error: "Not Found" }, { status: 404 }) |
| 4 | カスタムヘッダーを付与 | json(data, { headers }) | return json(data, { headers: { "X-Custom": "value" } }) |
| 5 | Cookie を設定 | json(data, { headers: { "Set-Cookie" } }) | headers: { "Set-Cookie": await commitSession(session) } |
| 6 | フォームエラーを返す | json({ errors }) | return json({ errors: { email: "無効です" } }) |
| 7 | 複数の Cookie を設定 | 複数の Set-Cookie ヘッダー | headers.append("Set-Cookie", cookie1) |
| 8 | ストリーミングレスポンス | new Response(stream) | return new Response(stream, { headers }) |
背景
Remix は、React ベースのフルスタックフレームワークとして、サーバーサイドとクライアントサイドをシームレスに統合する設計になっています。この設計の中核を担うのが Loader と Action です。
Loader はページのデータ取得を担当し、Action はフォーム送信などのデータ変更処理を担当します。どちらも Web 標準の Request オブジェクトを受け取り、Response オブジェクトを返すという、シンプルかつ強力な仕組みです。
しかし、このシンプルさゆえに「どの API をどう使えばいいのか」が散らばっており、毎回調べ直すことになりがちです。特に以下のような場面で迷いが生じます。
Remix における Loader と Action の基本的なデータフローを図で確認しましょう。
mermaidflowchart LR
client["クライアント<br/>ブラウザ"] -->|GET リクエスト| loader["Loader"]
client -->|POST/PUT/DELETE| action["Action"]
loader -->|データ取得| db[("データベース")]
action -->|データ更新| db
loader -->|json 応答| client
action -->|redirect または json| client
この図が示すように、Loader はデータ取得、Action はデータ変更を担当し、それぞれが Request を処理して Response を返します。
課題
Remix の Loader と Action を使いこなすには、以下のような課題があります。
API が散在している
URL パラメータの取得には new URL(request.url).searchParams を使い、Form データには request.formData() を使い、Cookie には request.headers.get("Cookie") を使うなど、API が散在しています。どの場面でどの API を使うべきか、記憶に頼るのは効率的ではありません。
Web 標準 API との違いが不明瞭
Remix は Web 標準の Request/Response API をベースにしていますが、Remix 独自のヘルパー関数(json()、redirect() など)も用意されています。「標準 API とヘルパーのどちらを使うべきか」が初見では分かりにくいのです。
エラーハンドリングのベストプラクティスが分散
フォームのバリデーションエラーを返す場合、Action でどのようなレスポンスを返せばいいのか。ステータスコードは 400 にすべきか、200 のまま errors フィールドを返すべきか。こうした判断基準が分散しています。
型安全性の確保が難しい
TypeScript を使っていても、formData.get() の戻り値は FormDataEntryValue | null 型であり、実際の型が不明瞭です。型アサーションを多用することになり、型安全性が損なわれがちです。
これらの課題を解決するには、実務でよく使うパターンを逆引き形式で整理し、すぐに参照できる形にまとめることが有効です。
Loader と Action が直面する課題を図で整理すると、以下のようになります。
mermaidflowchart TD
request["Request オブジェクト"] --> question1{"何を取得する?"}
question1 -->|URL パラメータ| api1["searchParams"]
question1 -->|Form データ| api2["formData"]
question1 -->|JSON| api3["json"]
question1 -->|Headers| api4["headers.get"]
response["Response 生成"] --> question2{"何を返す?"}
question2 -->|データ| json_helper["json ヘルパー"]
question2 -->|画面遷移| redirect_helper["redirect ヘルパー"]
question2 -->|エラー| error_response["json + status 400"]
解決策
これらの課題を解決するため、この記事では Remix の Loader/Action で頻出する Request/Response API を逆引き形式で整理します。
Request API の体系化
Request から情報を取得する API を、以下のカテゴリに分類します。
- URL 情報の取得: パラメータ、パス、クエリ文字列
- ボディ情報の取得: Form データ、JSON、テキスト
- メタ情報の取得: Headers、Cookies、メソッド
それぞれのカテゴリで、どの API をどう使えばいいのかを明示します。
Response API の体系化
Response を返す API を、以下のカテゴリに分類します。
- データレスポンス:
json()ヘルパー、カスタムヘッダー、ステータスコード - リダイレクトレスポンス:
redirect()ヘルパー、外部リダイレクト - エラーレスポンス: フォームエラー、API エラー、バリデーションエラー
これにより、「○○ をしたい」という目的から API を逆引きできるようになります。
実践的なコード例の提示
すべての API に対して、実際に動作するコード例を提示します。コピー&ペーストで即座に使える形にすることで、開発速度を向上させます。
TypeScript による型安全性の向上
formData.get() の戻り値を型安全に扱う方法、Zod などのバリデーションライブラリとの組み合わせ方など、型安全性を確保するパターンも紹介します。
具体例
ここからは、実際のコード例を交えながら、Request/Response API の使い方を解説していきます。
Request API の使い方
URL パラメータの取得
URL のクエリパラメータ(?page=2&sort=name など)を取得する方法です。
Remix の Loader では、request.url から URL オブジェクトを生成し、searchParams プロパティでクエリパラメータにアクセスできます。
typescriptimport { type LoaderFunctionArgs } from '@remix-run/node';
export async function loader({
request,
}: LoaderFunctionArgs) {
// URL オブジェクトを生成
const url = new URL(request.url);
// クエリパラメータを取得
const page = url.searchParams.get('page') || '1';
const sort = url.searchParams.get('sort') || 'name';
return { page, sort };
}
searchParams.get() は、パラメータが存在しない場合に null を返すため、デフォルト値を設定するのが一般的です。
複数の値を持つクエリパラメータ(?tags=react&tags=remix)を取得する場合は、getAll() を使います。
typescriptexport async function loader({
request,
}: LoaderFunctionArgs) {
const url = new URL(request.url);
// 複数の値を配列で取得
const tags = url.searchParams.getAll('tags');
// tags = ["react", "remix"]
return { tags };
}
パスパラメータの取得
動的ルート(routes/posts.$id.tsx など)のパラメータを取得する方法です。
Remix では、Loader や Action の第一引数に params オブジェクトが渡されます。ここからパスパラメータを取得できます。
typescriptimport { type LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function loader({
params,
}: LoaderFunctionArgs) {
// パスパラメータを取得
const postId = params.id;
// postId を使ってデータを取得
const post = await getPost(postId);
return json({ post });
}
パスパラメータは必ず存在するため、null チェックは不要ですが、TypeScript で厳密に型を付ける場合は params.id! とするか、バリデーションを行うと安全です。
Form データの取得
POST リクエストで送信されたフォームデータを取得する方法です。
Action では、request.formData() を使ってフォームデータを取得します。これは非同期メソッドなので、await が必要です。
typescriptimport { type ActionFunctionArgs } from '@remix-run/node';
import { json, redirect } from '@remix-run/node';
export async function action({
request,
}: ActionFunctionArgs) {
// フォームデータを取得
const formData = await request.formData();
// 各フィールドの値を取得
const username = formData.get('username');
const email = formData.get('email');
return json({ username, email });
}
formData.get() の戻り値は FormDataEntryValue | null 型(つまり string | File | null)なので、型安全に扱うにはバリデーションが必要です。
フォームデータのバリデーションを型安全に行う例を見てみましょう。
typescriptimport { type ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function action({
request,
}: ActionFunctionArgs) {
const formData = await request.formData();
// 文字列として取得し、バリデーション
const username = formData.get('username');
const email = formData.get('email');
// バリデーションエラーを収集
const errors: Record<string, string> = {};
if (!username || typeof username !== 'string') {
errors.username = 'ユーザー名は必須です';
}
if (
!email ||
typeof email !== 'string' ||
!email.includes('@')
) {
errors.email = '有効なメールアドレスを入力してください';
}
// エラーがあれば返す
if (Object.keys(errors).length > 0) {
return json({ errors }, { status: 400 });
}
// 処理を続行
return json({ success: true });
}
JSON ボディの取得
API エンドポイントとして使う場合、JSON ボディを取得する方法です。
request.json() を使うことで、JSON 形式のリクエストボディをパースできます。
typescriptimport { type ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function action({
request,
}: ActionFunctionArgs) {
// JSON ボディを取得
const data = await request.json();
// TypeScript の型アサーション
const { title, content } = data as {
title: string;
content: string;
};
return json({ title, content });
}
実務では、Zod などのスキーマバリデーションライブラリを使うことで、型安全性を確保できます。
typescriptimport { z } from 'zod';
import { type ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
// スキーマを定義
const PostSchema = z.object({
title: z.string().min(1, 'タイトルは必須です'),
content: z.string().min(10, '本文は10文字以上必要です'),
});
export async function action({
request,
}: ActionFunctionArgs) {
const data = await request.json();
// バリデーション
const result = PostSchema.safeParse(data);
if (!result.success) {
return json(
{ errors: result.error.flatten() },
{ status: 400 }
);
}
// 型安全なデータ
const { title, content } = result.data;
return json({ title, content });
}
Headers の取得
リクエストヘッダー(Authorization、User-Agent など)を取得する方法です。
request.headers.get() を使うことで、任意のヘッダーを取得できます。
typescriptimport { type LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function loader({
request,
}: LoaderFunctionArgs) {
// Authorization ヘッダーを取得
const authHeader = request.headers.get('Authorization');
if (!authHeader) {
return json(
{ error: '認証が必要です' },
{ status: 401 }
);
}
// Bearer トークンを抽出
const token = authHeader.replace('Bearer ', '');
return json({ token });
}
ヘッダーは大文字小文字を区別しないため、Authorization でも authorization でも同じ値を取得できます。
Cookie の取得
Cookie からセッション情報などを取得する方法です。
Cookie は Cookie ヘッダーに格納されているため、request.headers.get("Cookie") で取得し、パースする必要があります。
typescriptimport { type LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function loader({
request,
}: LoaderFunctionArgs) {
// Cookie ヘッダーを取得
const cookieHeader = request.headers.get('Cookie');
// cookie パーサーを使用(例: cookie パッケージ)
const cookies = cookieHeader
? Object.fromEntries(
cookieHeader.split('; ').map((c) => c.split('='))
)
: {};
const sessionId = cookies.sessionId;
return json({ sessionId });
}
実務では、Remix の createCookie や createCookieSessionStorage を使うことで、より安全に Cookie を扱えます。
typescriptimport { createCookie } from '@remix-run/node';
import { type LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
// Cookie を定義
const userPrefs = createCookie('user-prefs', {
maxAge: 60 * 60 * 24 * 365, // 1年
});
export async function loader({
request,
}: LoaderFunctionArgs) {
// Cookie を取得してパース
const prefs = await userPrefs.parse(
request.headers.get('Cookie')
);
return json({ theme: prefs?.theme || 'light' });
}
リクエストメソッドの確認
GET、POST、PUT、DELETE などのメソッドを確認する方法です。
Action は通常 POST メソッドで呼ばれますが、PUT や DELETE にも対応できます。request.method でメソッドを確認できます。
typescriptimport { type ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function action({
request,
}: ActionFunctionArgs) {
// リクエストメソッドを確認
const method = request.method;
switch (method) {
case 'POST':
// 新規作成
return json({ action: 'create' });
case 'PUT':
// 更新
return json({ action: 'update' });
case 'DELETE':
// 削除
return json({ action: 'delete' });
default:
return json(
{ error: 'サポートされていないメソッドです' },
{ status: 405 }
);
}
}
Form から method="POST" 以外のメソッドを送信したい場合は、hidden input で _method フィールドを使うのが一般的です。
Response API の使い方
JSON レスポンスを返す
最も基本的な JSON レスポンスの返し方です。
Remix の json() ヘルパーを使うことで、簡潔に JSON レスポンスを返せます。
typescriptimport { type LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function loader({
request,
}: LoaderFunctionArgs) {
const data = {
message: '成功しました',
timestamp: Date.now(),
};
// JSON レスポンスを返す
return json(data);
}
json() は内部で new Response(JSON.stringify(data), { headers: { "Content-Type": "application/json" } }) を実行しているため、手動で Response を作成する必要がありません。
ステータスコードを指定する
エラー時に 404 や 500 などのステータスコードを返す方法です。
json() の第二引数に { status } を渡すことで、ステータスコードを指定できます。
typescriptimport { type LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function loader({
params,
}: LoaderFunctionArgs) {
const post = await getPost(params.id);
// データが見つからない場合
if (!post) {
return json(
{ error: '投稿が見つかりませんでした' },
{ status: 404 }
);
}
return json({ post });
}
ステータスコード 404 を返すことで、Remix の ErrorBoundary が自動的に呼ばれます。
バリデーションエラーを返す場合は、ステータスコード 400 を使います。
typescriptimport { type ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function action({
request,
}: ActionFunctionArgs) {
const formData = await request.formData();
const email = formData.get('email');
// バリデーションエラー
if (
!email ||
typeof email !== 'string' ||
!email.includes('@')
) {
return json(
{
errors: {
email: '有効なメールアドレスを入力してください',
},
},
{ status: 400 }
);
}
return json({ success: true });
}
カスタムヘッダーを付与する
キャッシュ制御や CORS ヘッダーなど、カスタムヘッダーを付与する方法です。
json() の第二引数に { headers } を渡すことで、カスタムヘッダーを追加できます。
typescriptimport { type LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function loader({
request,
}: LoaderFunctionArgs) {
const data = { message: 'キャッシュ可能なデータ' };
// カスタムヘッダーを付与
return json(data, {
headers: {
'Cache-Control': 'public, max-age=3600',
'X-Custom-Header': 'MyValue',
},
});
}
CORS を有効にする場合も、同様にヘッダーを追加します。
typescriptimport { type LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function loader({
request,
}: LoaderFunctionArgs) {
const data = { message: 'CORS が有効です' };
return json(data, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods':
'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers':
'Content-Type, Authorization',
},
});
}
Cookie を設定する
レスポンスに Cookie を設定する方法です。
Set-Cookie ヘッダーを使うことで、Cookie を設定できます。Remix の createCookie ヘルパーを使うと、より安全に Cookie を設定できます。
typescriptimport { createCookie } from '@remix-run/node';
import { type ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
// Cookie を定義
const themeCookie = createCookie('theme', {
maxAge: 60 * 60 * 24 * 365, // 1年
httpOnly: true,
secure: true,
sameSite: 'lax',
});
export async function action({
request,
}: ActionFunctionArgs) {
const formData = await request.formData();
const theme = formData.get('theme') as string;
// Cookie を設定
return json(
{ success: true },
{
headers: {
'Set-Cookie': await themeCookie.serialize(theme),
},
}
);
}
複数の Cookie を設定する場合は、Headers オブジェクトを使います。
typescriptimport { type ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function action({
request,
}: ActionFunctionArgs) {
const headers = new Headers();
// 複数の Cookie を追加
headers.append(
'Set-Cookie',
'cookie1=value1; Path=/; HttpOnly'
);
headers.append(
'Set-Cookie',
'cookie2=value2; Path=/; HttpOnly'
);
return json({ success: true }, { headers });
}
リダイレクトする
ログイン後のダッシュボードへの遷移など、リダイレクトする方法です。
Remix の redirect() ヘルパーを使うことで、簡潔にリダイレクトできます。
typescriptimport { type ActionFunctionArgs } from '@remix-run/node';
import { redirect } from '@remix-run/node';
export async function action({
request,
}: ActionFunctionArgs) {
const formData = await request.formData();
const username = formData.get('username') as string;
// ユーザーを作成
await createUser(username);
// ダッシュボードにリダイレクト
return redirect('/dashboard');
}
デフォルトでは 302 リダイレクトが返されますが、ステータスコードを変更することもできます。
typescriptimport { type ActionFunctionArgs } from '@remix-run/node';
import { redirect } from '@remix-run/node';
export async function action({
request,
}: ActionFunctionArgs) {
await deleteUser();
// 301 永続的なリダイレクト
return redirect('/', { status: 301 });
}
リダイレクト時に Cookie を設定する場合は、headers オプションを使います。
typescriptimport { createCookieSessionStorage } from '@remix-run/node';
import { type ActionFunctionArgs } from '@remix-run/node';
import { redirect } from '@remix-run/node';
const { getSession, commitSession } =
createCookieSessionStorage({
cookie: {
name: '__session',
httpOnly: true,
secure: true,
},
});
export async function action({
request,
}: ActionFunctionArgs) {
const session = await getSession(
request.headers.get('Cookie')
);
// セッションにデータを設定
session.set('userId', '12345');
// Cookie を設定してリダイレクト
return redirect('/dashboard', {
headers: {
'Set-Cookie': await commitSession(session),
},
});
}
フォームエラーを返す
フォームのバリデーションエラーをクライアントに返す方法です。
Remix では、Action から json({ errors }) を返すことで、コンポーネント側で useActionData() を使ってエラーを取得できます。
typescriptimport { type ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function action({
request,
}: ActionFunctionArgs) {
const formData = await request.formData();
const email = formData.get('email') as string;
const password = formData.get('password') as string;
const errors: Record<string, string> = {};
// バリデーション
if (!email || !email.includes('@')) {
errors.email = '有効なメールアドレスを入力してください';
}
if (!password || password.length < 8) {
errors.password = 'パスワードは8文字以上必要です';
}
// エラーがあれば返す
if (Object.keys(errors).length > 0) {
return json({ errors }, { status: 400 });
}
// 成功時の処理
return redirect('/dashboard');
}
クライアント側では、useActionData() を使ってエラーを表示します。
typescriptimport { useActionData } from '@remix-run/react';
export default function LoginPage() {
const actionData = useActionData<typeof action>();
return (
<form method='post'>
<div>
<label>メールアドレス</label>
<input type='email' name='email' />
{actionData?.errors?.email && (
<p style={{ color: 'red' }}>
{actionData.errors.email}
</p>
)}
</div>
<div>
<label>パスワード</label>
<input type='password' name='password' />
{actionData?.errors?.password && (
<p style={{ color: 'red' }}>
{actionData.errors.password}
</p>
)}
</div>
<button type='submit'>ログイン</button>
</form>
);
}
実践的な統合例
Loader と Action を組み合わせた、実践的な CRUD 操作の例を見てみましょう。
以下は、ブログ投稿の編集ページの例です。Loader でデータを取得し、Action で更新を処理します。
typescriptimport {
type LoaderFunctionArgs,
type ActionFunctionArgs,
} from '@remix-run/node';
import { json, redirect } from '@remix-run/node';
import {
useLoaderData,
useActionData,
Form,
} from '@remix-run/react';
// Loader: 編集対象の投稿を取得
export async function loader({
params,
}: LoaderFunctionArgs) {
const post = await getPost(params.id);
if (!post) {
return json(
{ error: '投稿が見つかりませんでした' },
{ status: 404 }
);
}
return json({ post });
}
// Action: 投稿を更新
export async function action({
request,
params,
}: ActionFunctionArgs) {
const formData = await request.formData();
const title = formData.get('title') as string;
const content = formData.get('content') as string;
// バリデーション
const errors: Record<string, string> = {};
if (!title || title.length < 3) {
errors.title = 'タイトルは3文字以上必要です';
}
if (!content || content.length < 10) {
errors.content = '本文は10文字以上必要です';
}
if (Object.keys(errors).length > 0) {
return json({ errors }, { status: 400 });
}
// 更新処理
await updatePost(params.id, { title, content });
// 詳細ページにリダイレクト
return redirect(`/posts/${params.id}`);
}
コンポーネント側では、Loader のデータと Action のエラーを組み合わせて表示します。
typescriptexport default function EditPost() {
const { post } = useLoaderData<typeof loader>();
const actionData = useActionData<typeof action>();
return (
<div>
<h1>投稿を編集</h1>
<Form method='post'>
<div>
<label>タイトル</label>
<input
type='text'
name='title'
defaultValue={post.title}
/>
{actionData?.errors?.title && (
<p style={{ color: 'red' }}>
{actionData.errors.title}
</p>
)}
</div>
<div>
<label>本文</label>
<textarea
name='content'
defaultValue={post.content}
rows={10}
/>
{actionData?.errors?.content && (
<p style={{ color: 'red' }}>
{actionData.errors.content}
</p>
)}
</div>
<button type='submit'>更新</button>
</Form>
</div>
);
}
この例では、Loader でデータを取得し、Action でバリデーションと更新を行い、エラーがあればフォームに表示し、成功すればリダイレクトするという、典型的な CRUD パターンを実装しています。
Request と Response の処理フローを図で確認しましょう。
mermaidsequenceDiagram
participant User as ユーザー
participant Remix as Remix アプリ
participant Loader as Loader 関数
participant Action as Action 関数
participant DB as データベース
User->>Remix: GET /posts/123
Remix->>Loader: loader({ params, request })
Loader->>DB: データ取得
DB-->>Loader: Post データ
Loader-->>Remix: json({ post })
Remix-->>User: HTML + データ
User->>Remix: POST /posts/123 (Form 送信)
Remix->>Action: action({ params, request })
Action->>Action: formData 取得
Action->>Action: バリデーション
alt エラーあり
Action-->>Remix: json({ errors }, 400)
Remix-->>User: エラー表示
else 成功
Action->>DB: データ更新
DB-->>Action: 完了
Action-->>Remix: redirect("/posts/123")
Remix-->>User: リダイレクト
end
まとめ
この記事では、Remix の Loader と Action で使える Request/Response API を逆引き形式でまとめました。
Request API では、以下の取得方法を解説しました。
- URL パラメータ:
new URL(request.url).searchParams - パスパラメータ:
paramsオブジェクト - Form データ:
await request.formData() - JSON ボディ:
await request.json() - Headers:
request.headers.get() - Cookie:
request.headers.get("Cookie")+ パース - リクエストメソッド:
request.method
Response API では、以下の返し方を解説しました。
- JSON レスポンス:
json(data) - ステータスコード指定:
json(data, { status }) - カスタムヘッダー:
json(data, { headers }) - Cookie 設定:
Set-Cookieヘッダー - リダイレクト:
redirect(url) - フォームエラー:
json({ errors }, { status: 400 })
これらの API を組み合わせることで、Remix で堅牢な Web アプリケーションを開発できます。開発中に「あれ、これどうやるんだっけ?」と思ったら、ぜひこの記事を参照してください。
早見表を印刷して手元に置いておくと、さらに開発効率が向上するでしょう。Remix の Loader と Action を使いこなして、快適な開発体験を手に入れてください。
関連リンク
articleRemix Loader/Action チートシート:Request/Response API 逆引き大全
articleRemix × Vite 構成の作り方:開発サーバ・ビルド・エイリアス設定【完全ガイド】
articleRemix を選ぶ基準:認証・API・CMS 観点での要件適合チェック
articleRemix の仕組みを図解で理解:ルーティング/データロード/アクションの全体像
articleRemix で「Hydration failed」を解決:サーバ/クライアント不整合の診断手順
articleRemix 本番運用チェックリスト:ビルド・監視・バックアップ・脆弱性対応
articlePinia ストアスキーマの変更管理:バージョン付与・マイグレーション・互換ポリシー
articleshadcn/ui コンポーネント置換マップ:用途別に最短でたどり着く選定表
articleOllama のコスト最適化:モデルサイズ・VRAM 使用量・バッチ化の実践
articleRemix Loader/Action チートシート:Request/Response API 逆引き大全
articleObsidian タスク運用の最適解:Tasks + Periodic Notes で計画と実行を接続
articlePreact Signals チートシート:signal/computed/effect 実用スニペット 30
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来