概要
- Ant Design
- material UI
の2つでform validationを実装する。
まえがき
今年の初めにAnt Designでform validationを実装したところ、
少し詰まった & 理解できてない部分があったので、整理しようと着手しました。
するとアップデートされていたようで一瞬でできてしまったので、material UI でも試してみることに。
実装
Ant Design
コード
import { Form, Input, Button, Checkbox } from "antd";
const App = () => {
const onFinish = (values: any) => {
console.log("Success:", values);
};
const onFinishFailed = (errorInfo: any) => {
console.log("Failed:", errorInfo);
};
const USERNAME = ["test", "same name"];
return (
<Form
name="basic"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
initialValues={{ remember: true }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item
label="Username(same nameと入力してfocusを外すとエラーが出ます。文字数制限は4~100)"
name="username"
validateTrigger="onBlur"
rules={[
{
min: 4,
max: 100,
message: "Usernameは最低4文字最大100文字でお願いします"
},
{
validator: async (_, value) => {
USERNAME.map((name) => {
if (name === value) {
throw new Error("この名前は既に使用されています");
} else {
return Promise.resolve();
}
});
}
}
]}
>
<Input />
</Form.Item>
<Form.Item
label="Password(入力ごとにvalidationが走ります。default設定)"
name="password"
rules={[
{
min: 4,
max: 8,
message: "Passwordは最低4文字最大8文字でお願いします"
},
{
required: true,
message: "Passwordは必須です"
}
]}
>
<Input.Password />
</Form.Item>
<Form.Item
name="remember"
valuePropName="checked"
wrapperCol={{ offset: 8, span: 16 }}
>
<Checkbox>Remember me</Checkbox>
</Form.Item>
<Form.Item wrapperCol={{ offset: 8, span: 16 }}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
export default App;
Ant Designは公式がかなり読みやすくなってたので、ぜひ読むのお勧めします。めんどくさがらずに。
基本的にはrulesの中にvalidation ruleを入れていきます。
例えば min: 4
だと最小4文字ってことですね。
カスタマイズしたい時は validator
の中で関数を書いてください。
validationのタイミングは初期値がonChange(入力毎)です。
変更したい場合は validateTrigger
を変更します。
非常にわかりやすい構成でした。
material UI
公式を見ていると
<TextField inputProps={{ inputMode: 'numeric', pattern: '[0-9]*' }} />
みたいな記述は見つけて…あれ…これだけ?
と思い TextFieldAPIで valida
と検索かけるもヒットせず。
あれ…
と思って見返してたら、
For more advanced use cases, you might be able to take advantage of:
react-hook-form: React hook for form validation.
(もっとカスタマイズしたかったら、react-hook-form使うといいやで)
まじですCAR
Ant Designが親切すぎただけかな。
material UI + react hook form
import React from "react";
import { useForm, Controller, SubmitHandler } from "react-hook-form";
import Input from "@material-ui/core/Input";
interface IFormInput {
firstName: string;
}
const App = () => {
const {
getValues,
control,
handleSubmit,
formState: { errors }
} = useForm<IFormInput>({ mode: "onBlur" });
const onSubmit: SubmitHandler<IFormInput> = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>Username(same name と打つとエラーが出ます)</label>
<br />
<Controller
name="firstName"
control={control}
defaultValue=""
render={({ field }) => <Input {...field} />}
rules={{
validate: () => {
return getValues("firstName") !== "same name";
}
}}
/>
{errors.firstName && <div>その名前は既に利用されています。</div>}
<p>
<input type="submit" />
</p>
</form>
);
};
export default App;
react hook formの公式初めて読んだんですがめちゃわかりやすい。日本語ですし、情報も整理されててよき。
これは react hook form
の中に material UI
を組み込んで使用した例です。
render
の中の Input
がmaterial UIの部分ですね。
こちらもAnt Designと同様に rules
の validate
の中にいろいろ書いていけます。
validationのタイミングは useForm<IFormInput>({ mode: "onBlur" });
ここで変更できます。
その他の詳細は公式わかりやすすぎたので、そちらがいいかと。
ちなみに
react hook form は Ant Designにも対応してるようなので、Ant Designだけでどうにもならない場合はreact hook form への組み込みご検討ください。
まとめ
react hook formのおかげで大体なんとかなりそう。
FrameWork UIのカスタマイズは面倒なイメージですが、綺麗にwrapしてくれてました。
(コードはちゃちゃっと作ったものでプロダクトで試しておらず、簡易な動作確認しかしていないのでその点はご了承ください)
あとがき
Ant Designで最初に実装した時は
「formはasync validatorを使ってるから詳しくはそっちみて」とGitHubのURLがあるだけで、
欲しい情報も中国語の掲示板にあったりして苦労した記憶があったのですが、
久しぶりに見返すととてもよかった。
Ant DesignのUI個人的には好きなんですが、シェア率低くて記事がないのがつらい…
(QiitaでもAntDesignのtag23個しかなかったし)