next.jsのappルーターでのフォームの作り方が不安だったので学習する。
内容としては公式チュートリアル第12章(https://nextjs.org/learn/dashboard-app/mutating-data)
作るフォームは、ユーザーネームとe-mailを送信するシンプルなもの。
バリデーションに成功したらホームにリダイレクトさせる。
バリデーションはhtml5の機能を使ってクライアントサイドで実行&zodでサーバーで実行させる。
app/form/page.js
"use client";
import { createUser } from "@/lib/actions";
export default function Form() {
return (
<form action={createUser}>
<div>
<label htmlFor="userName"> user name </label>
<input
id="userName"
name="userName"
type="text"
placeholder="Enter userName"
/>
</div>
<div>
<label htmlFor="email">email</label>
<input id="email" name="email" type="email" placeholder="Enter email" />
</div>
<button type="submit">submit</button>
</form>
);
}
app/lib/actions.js
"use server";
import { z } from "zod";
import { redirect } from "next/navigation";
const userSchema = z.object({
userName: z.string(),
email: z.string().email(),
});
export async function createUser(formData) {
const { userName, email } = userSchema.parse({
userName: formData.get("userName"),
email: formData.get("email"),
});
console.log({ userName: userName, email: email });
redirect("/");
}
app/page.js
import Link from "next/link";
export default function Home() {
return (
<main>
<div>
<Link href="/form">フォーム</Link>
</div>
</main>
);
}
入力画面(http://localhost:3000/form)
サブミット後のコンソール
- ホームへのリダイレクト
- メールアドレスを「xxx@xxx」の形式で送信したときにzodのバリデーションで拒否されること
- javascriptを無効化してもフォームが送信されること
を確認できた。
内部的にはAPIを作成してformDataをpostしてくれているらしい。
js無効にしてもフォームの送信が可能となっている点は、プログレッシブエンハンスメント(https://developer.mozilla.org/ja/docs/Glossary/Progressive_Enhancement)という考え方のためらしい。これは最新のブラウザですべてのコードが有効な時に最良の体験を提供するが、古いブラウザでコードの一部が利用できなくても問題なく動作するようにページを作ることをいうらしい。(チョーざっくり解釈。)
これくらい簡単なフォームだとjsオンオフの差を感じないが、フォームが大きくなるとレンダリング周りで差が出てくるのだろうか。
sendgridでメール送信する問い合わせフォームにしようかなと思うので一応デプロイ
github:https://github.com/makotoStudying/form-app
アプリ:https://form-app-hazel.vercel.app/
appルーターに関しては、チュートリアル12章でも使われているrevalidatePathのようなキャッシュ操作についても学習しないといけないなと思う。(おそらくappルーターのキモだと思われる)
以上