基本の使い方
Mantine の useForm
は、フォームのバリデーション、初期値設定、値の変更トラッキング、エラー管理を簡潔に実装できるフックです。
import { useForm } from '@mantine/form';
const form = useForm({
initialValues: {
email: '',
password: '',
},
validate: {
email: (value) => (/^\S+@\S+$/.test(value) ? null : '無効なメールアドレス'),
password: (value) =>
value.length >= 6 ? null : 'パスワードは6文字以上である必要があります',
},
});
各部分の解説
① import { useForm } from '@mantine/form'
- Mantine が提供する
useForm
フックをインポートします。
② const form = useForm({ ... })
-
useForm
を呼び出すと、「フォームの状態や操作を管理するオブジェクト」が返ってきます。 - 返される
form
はオブジェクトで、値・エラー・バリデーション・イベント処理関数などが入っています。
③ initialValues
initialValues: {
email: '',
password: '',
}
- フォームの初期値を設定します。
-
form.values.email
やform.values.password
にこの値が入ります。 -
<input {...form.getInputProps("email")} />
などでこれらの値がバインドされます。
④ validate
validate: {
email: (value) => (/^\S+@\S+$/.test(value) ? null : '無効なメールアドレス'),
password: (value) => value.length >= 6 ? null : 'パスワードは6文字以上である必要があります',
}
- 各フィールドのバリデーション関数を定義します。
- 関数は
null
を返せば「OK」、エラーメッセージ文字列を返すと「エラー」扱いになります。 -
form.validate()
やform.onSubmit()
のときに実行されます。
イメージとしては…
const form = {
values: { ... }, // 各フィールドの現在の値
errors: { ... }, // 各フィールドのバリデーションエラー
setFieldValue: fn(), // 値をプログラムで更新
validate: fn(), // バリデーションを実行
getInputProps: fn(), // 各inputに必要なpropsを生成
onSubmit: fn(), // submitイベントをラップ
reset: fn(), // 初期状態にリセット
... そのほか
}
つまり、form = 「フォームの操作・情報が詰まった道具箱」という感覚です。
よくあるユースケース
ユースケース1:ログインフォーム
要件
- ユーザーがメールアドレスとパスワードを入力
- バリデーションが必要(メール形式、パスワード6文字以上)
実装
import { TextInput, Button } from '@mantine/core';
import { useForm } from '@mantine/form';
function LoginForm() {
const form = useForm({
initialValues: {
email: '',
password: '',
},
validate: {
email: (value) => (/^\S+@\S+$/.test(value) ? null : '無効なメールアドレス'),
password: (value) =>
value.length >= 6 ? null : 'パスワードは6文字以上である必要があります',
},
});
const handleLogin = (values: typeof form.values) => {
console.log('ログイン処理:', values);
// API へログインリクエスト送信など
};
return (
<form onSubmit={form.onSubmit(handleLogin)}>
<TextInput label="メールアドレス" {...form.getInputProps('email')} />
<TextInput label="パスワード" type="password" {...form.getInputProps('password')} />
<Button type="submit">ログイン</Button>
</form>
);
}
ユースケース2:プロフィール編集フォーム(APIと連携)
要件
- ユーザー名、年齢を編集可能
- フォーム初期値は API から取得してセット
- 年齢は数値として扱う(文字列→数値変換あり)
実装例
import { TextInput, Button, NumberInput } from '@mantine/core';
import { useForm } from '@mantine/form';
import { useEffect } from 'react';
function ProfileForm() {
const form = useForm({
initialValues: {
name: '',
age: 0,
},
validate: {
name: (value) => (value ? null : '名前は必須です'),
age: (value) => (value > 0 ? null : '年齢は正の数である必要があります'),
},
});
// ダミーAPI呼び出し
useEffect(() => {
fetch('/api/me')
.then((res) => res.json())
.then((data) => {
form.setValues({
name: data.name,
age: data.age,
});
});
}, []);
const handleSubmit = (values: typeof form.values) => {
console.log('更新データ:', values);
// PUT /api/me に送信など
};
return (
<form onSubmit={form.onSubmit(handleSubmit)}>
<TextInput label="名前" {...form.getInputProps('name')} />
<NumberInput label="年齢" {...form.getInputProps('age')} />
<Button type="submit">更新</Button>
</form>
);
}
ユースケース3:チェックボックス付きの同意フォーム
要件
- 規約に同意したらボタンが有効になる
実装例
import { Checkbox, Button } from '@mantine/core';
import { useForm } from '@mantine/form';
function ConsentForm() {
const form = useForm({
initialValues: {
agreed: false,
},
validate: {
agreed: (value) => (value ? null : '同意が必要です'),
},
});
return (
<form onSubmit={form.onSubmit((v) => console.log(v))}>
<Checkbox label="利用規約に同意します" {...form.getInputProps('agreed', { type: 'checkbox' })} />
<Button type="submit" disabled={!form.values.agreed}>送信</Button>
</form>
);
}
知識ポイントまとめ
ポイント | 説明 | 補足 |
---|---|---|
form.getInputProps('name') |
<input> に value , onChange , error などを自動付与 |
ほぼ必須の使い方。これでフォームと状態が連携される |
form.values |
フォームの全フィールドの現在の値 | 送信時やログ出力に使う |
form.errors |
各フィールドのバリデーションエラー(あれば) | UIでエラー表示に使える |
form.validate() |
現在の状態に対して全体バリデーションを実行 | 手動でバリデーションしたいときに使う |
form.setFieldValue('field', value) |
特定フィールドの値をプログラムで変更 | APIや副作用から値をセットするときに使う |
form.setValues({...}) |
複数フィールドをまとめて更新 | APIから初期値をセットするときに便利 |
form.reset() |
初期状態に戻す | 編集フォームのキャンセルなどで使用 |
form.onSubmit(handler) |
<form> の onSubmit に渡す用のハンドラ |
バリデーション付きで安全な送信を実現 |
useForm
は「Reactの状態管理」と「フォームのバリデーション・入力UI」を自動でつなげてくれる仕組み。
よくある落とし穴・注意点
1. getInputProps
は 使う型に合わせて指定が必要
例:
<Checkbox {...form.getInputProps('agreed', { type: 'checkbox' })} />
落とし穴:
<Checkbox {...form.getInputProps('agreed')} /> // ← これだと `true/false` が効かない
type: 'checkbox'
を明示しないと、value
が正しく動作しない。
2. initialValues
の値の型が実際の UI と一致していないとエラーや不具合になる
例:
initialValues: { age: 0 }
// 実際は TextInput を使っていて、文字列になる → バリデーションで型がずれる
対策:
-
NumberInput
やSelect
を使うときは型を合わせるか、バリデーションやonChange
で型変換を明示的にする
3. form.validate()
は フィールドごとのバリデーション関数に依存
- フィールドが
validate
に定義されていないと、チェックされない - 逆に、不要なフィールドに
validate
を残すと無意味にバリデーションされる
対策:validate
オブジェクトは使っているフィールドだけにする
4. form.reset()
は初期値に戻すだけ。現在の値は保存されない
- 「編集を一時保存 → リセットで戻す」ような挙動を想定してると意図とズレる
対策:form.values
をコピーして退避しておくなどで対応
5. getInputProps()
を使わずに value
, onChange
を手動管理しようとすると混乱しやすい
例:
<input value={form.values.name} onChange={(e) => setSomething(e.target.value)} />
→ useForm
の状態と同期しなくなり、フォームが壊れることがある
対策:基本的にはすべて getInputProps()
に任せる
6. validateInputOnChange
, validateInputOnBlur
の動作を把握していないと混乱する
- デフォルトでは、バリデーションは
submit
時だけ -
validateInputOnBlur: true
を設定すると blur 時にバリデーションされる
明示的に動作を設定した方が、意図通りに動きやすい
const form = useForm({
initialValues: { name: '' },
validate: { ... },
validateInputOnBlur: true, // 入力欄を離れたときにチェック
});
まとめ
useForm
は、React のフォーム管理をシンプルかつ直感的にする強力なフック
useForm
= React における「フォーム状態・バリデーション・イベント」のすべてを一元管理するハブ