インテントボタン
送信ボタンがフォームの送信を行う際、それは submitter として機能し、フォームデータに含まれることになります。
#送信のインテント
submitter は、インテント(意図)に基づいて異なる振る舞いでフォームを拡張したい場合に特に便利です。
1import { useForm } from '@conform-to/react';
2
3function Product() {
4 const [form] = useForm({
5 onSubmit(event, { formData }) {
6 event.preventDefault();
7
8 switch (formData.get('intent')) {
9 case 'add-to-cart':
10 // カートに追加
11 break;
12 case 'buy-now':
13 // 購入
14 break;
15 }
16 },
17 });
18
19 return (
20 <form id={form.id}>
21 <input type="hidden" name="productId" value="rf23g43" />
22 <button type="submit" name="intent" value="add-to-cart">
23 Add to Cart
24 </button>
25 <button type="submit" name="intent" value="buy-now">
26 Buy now
27 </button>
28 </form>
29 );
30}
#フォームのコントロール
Conform は、フィールドのバリデーションや削除など、すべてのフォームコントロールに対して送信のインテントを利用します。これは、ボタンに予約された名前を与え、インテントを値としてシリアライズすることで成されます。設定を簡素化するために、 Conform は form.validate
、 form.reset
、 form.insert
などの一連のフォームコントロールヘルパーを提供します。
バリデート インテント
バリデーションをトリガーするには、バリデート インテントを使用してボタンを構成できます。
1import { useForm } from '@conform-to/react';
2
3function EmailForm() {
4 const [form, fields] = useForm();
5
6 return (
7 <form id={form.id}>
8 <input name={fields.email.name} />
9 <button {...form.validate.getButtonProps({ name: fields.email.name })}>
10 Validate Email
11 </button>
12 </form>
13 );
14}
ボタンがクリックされると、 Conform は予約された名前でシリアライズされたインテントを識別し、メールフィールドを検証済みとしてマークすることによりバリデーションをトリガーし、メールが無効である場合はエラーメッセージを返します。
しかし、ユーザーがフィールドを離れた時点でバリデーションをトリガーしたい場合は、バリデート インテントを直接トリガーすることもできます。
1import { useForm } from '@conform-to/react';
2
3function EmailForm() {
4 const [form, fields] = useForm();
5
6 return (
7 <form id={form.id}>
8 <input
9 name={fields.email.name}
10 onBlur={(event) => form.validate({ name: event.target.name })}
11 />
12 </form>
13 );
14}
reset および update インテント
reset および update のインテントを使ってフィールドを変更することもできます。
1import { useForm } from '@conform-to/react';
2
3export default function Tasks() {
4 const [form, fields] = useForm();
5
6 return (
7 <form id={form.id}>
8 <button {...form.reset.getButtonProps()}>Reset form</button>
9 <button
10 {...form.reset.getButtonProps({
11 name: fields.tasks.name,
12 })}
13 >
14 Reset field (including nested / list field)
15 </button>
16 <button
17 {...form.update.getButtonProps({
18 name: fields.agenda.name,
19 value: {
20 title: 'My agenda',
21 description: 'This is my agenda',
22 },
23 })}
24 >
25 Update field (including nested / list field)
26 </button>
27 <button
28 {...form.update.getButtonProps({
29 validated: false,
30 })}
31 >
32 Clear all error
33 </button>
34 </form>
35 );
36}
両方のインテントを使用するには、フィールドメタデータから key を使って入力を設定する必要があります。 Conform はこのキーに依存して、更新された initialValue で input を再マウントするための React への通知を行います。唯一の例外は、 useInputControl フックを使用して制御された入力を設定している場合で、 key が変更されると値がリセットされます。
insert、remove、および reorder (並び替え) インテント
フィールドリストを操作するには、 insert 、 remove 、 reorder のインテントを使用できます。
1import { useForm } from '@conform-to/react';
2import { parseWithZod } from "@conform-to/zod";
3import { z } from "zod";
4
5const todosSchema = z.object({
6 title: z.string(),
7 tasks: z.array(z.string()),
8});
9
10export default function Tasks() {
11 const [form, fields] = useForm({
12 onValidate({ formData }) {
13 return parseWithZod(formData, { schema: todosSchema });
14 },
15 shouldValidate: "onBlur",
16 });
17 const tasks = fields.tasks.getFieldList();
18
19 return (
20 <form id={form.id} onSubmit={form.onSubmit}>
21 <ul>
22 {tasks.map((task, index) => (
23 <li key={task.key}>
24 <input name={task.name} />
25 <button
26 {...form.reorder.getButtonProps({
27 name: fields.tasks.name,
28 from: index,
29 to: 0,
30 })}
31 >
32 Move to top
33 </button>
34 <button
35 {...form.remove.getButtonProps({
36 name: fields.tasks.name,
37 index,
38 })}
39 >
40 Delete
41 </button>
42 </li>
43 ))}
44 </ul>
45 <button
46 {...form.insert.getButtonProps({
47 name: fields.tasks.name,
48 })}
49 >
50 Add task
51 </button>
52 <button>Save</button>
53 </form>
54 );
55}