LoginSignup
3
0

More than 1 year has passed since last update.

React + FrameWork UI の form validationについて

Last updated at Posted at 2021-11-08

概要

  • 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]*' }} />

みたいな記述は見つけて…あれ…これだけ?
と思い TextFieldAPIvalidaと検索かけるもヒットせず。

あれ…
と思って見返してたら、

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と同様に rulesvalidate の中にいろいろ書いていけます。
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個しかなかったし)

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0