Cookies
The loader reads request.headers.get("cookie"); the action returns a Response whose set-cookie header threads out to the browser. Subsequent loads see the cookie.
Tip
The POST/Redirect/GET pattern here is essential: if the action returned 200, the browser would navigate to the action's response body instead of reloading the page. The 303 forces a clean GET under the new cookie state.
Cookies the server sees on this request
(no cookies present)
Click "Set", then refresh — you should see demo_session in the cookie list above.
// src/app/examples/cookies/page.tsx (loader + action)
export async function loader({ request }: LoaderArgs) {
const cookies = parseCookies(request.headers.get("cookie") ?? "");
return { cookies };
}
export async function action({ request }: ActionArgs) {
const form = await request.formData();
const op = String(form.get("op") ?? "");
// 303 POST/Redirect/GET — forces the browser to re-fetch under the
// new cookie state. Returning 200 here would navigate to the action
// response body instead of reloading the page.
if (op === "set") {
return new Response(null, {
status: 303,
headers: {
"location": "/examples/cookies",
"set-cookie": "demo_session=abc123; Path=/; Max-Age=300; SameSite=Lax",
},
});
}
if (op === "clear") {
return new Response(null, {
status: 303,
headers: {
"location": "/examples/cookies",
"set-cookie": "demo_session=; Path=/; Max-Age=0; SameSite=Lax",
},
});
}
return { ok: true };
}