0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React / react-hook-form / zod でのForm 実装

Posted at

はじめに

使用ライブラリ

React-hook-form : フォームの値の制御やValidationが簡単でできるすごいやつ
zod : 型定義が便利らしい。

使用経験

React-hook-form : メインで触ってはないですが、業務で 触っていました。
zod :触ったことないですが、便利らしいのでこの機会に学んでみようかと

設計

下記で作成した、ものを対象に React-hook-form ログイン時にValitadion をつけていきましょう。

Login.jsx
import { Box, Button, Paper, TextField, Typography } from '@mui/material';

export const  Login = () => {
  return (
    <>
      <Paper
        elevation={3}
        sx={{
          borderRadius: 6,
          p: 4,
          height: '70vh',
          width: '280px',
          m: '20px auto',
        }}
      >
        <Box
          mt={8}
          display='flex'
          flexDirection='column'
          gap={5}
          alignItems='center'
        >
          <Typography variant='h5' fontWeight="bold">ログイン画面</Typography>
          <TextField
            type='id'
            name='user_id'
            variant='standard'
            placeholder='ユーザーIDを入力してください'
            fullWidth
          />
          <TextField
            type='password'
            name='password'
            variant='standard'
            placeholder='パスワードを入力してください'
            fullWidth
          />
          <Button type='submit' color='primary' variant='contained' fullWidth>
            ログイン
          </Button>
        </Box>
      </Paper>
    </>
  );
}

スクリーンショット 2023-01-28 20.05.24.png

上記の ログインをクリックしたら、Validation で引っかかる or 成功する といった風に実装していきましょう。

普通ログイン画面でこういう Validation はかけませんが、想定として

ID : メースアドレスの形式
PW : 8文字以上、32文字以下、半角英語、半角数字を含む

このような形で想定しておきます。

じゃあ実装しましょ〜

実装

react-hook-form

npm i react-hook-form で react-hook-form を install します。

Login.jsx
import { Box, Button, Paper, TextField, Typography } from '@mui/material';
// import する
import { useForm } from "react-hook-form";


export const Login = () => {
  

  const { register, handleSubmit, watch, formState: { errors } } = useForm();


  return (
                    --- 省略 ---
  );
}

const { register, handleSubmit, watch, formState: { errors } } = useForm();
のように、useFormを使用します。
下記簡単な解説です。あとで実装時に見返してもらえればここでわからなくてもいいです。

  • register : 各 input 要素に どのような名前が対応するか設定するためのもの、Validationもこの中でかけれる。
  • handleSubmit: form にわたして、登録ボタン押下時に行う処理を記述
  • watch : リアルタイムで今入っている値を管理する。
  • errors : validation に引っかかった場合のエラーを管理する。

登録時の処理を設定

登録時の処理を関数とする。

  /**
   * 登録時の処理を関数化
   * @param  data formから受け取る値
   */
  const onSubmit = (data) => {
    // アラートで結果出してみる (見やすいようにJSON 形式にする)
    alert(JSON.stringify(data));
  };

form タグに 登録時処理を渡す。

 <form onSubmit={handleSubmit(onSubmit)}>

各要素への命名を設定

適当な命名を 各TextFieldへregisterを用いて設定する。

            <TextField
              type='id'
              name='id'
              {...register('id')}
              variant='standard'
              placeholder='ユーザーIDを入力してください'
              fullWidth
            />
            <TextField
              type='password'
              name='password'
              {...register('password')}
              variant='standard'
              placeholder='パスワードを入力してください'
              fullWidth
            />

この段階で、Validation は設定できていないが、ログインボタンを押すと、値が受け取れていることを確認する。

スクリーンショット 2023-01-28 20.38.18.png

Validation の実装

    <TextField
              type='id'
              name='id'
              {...register('id', { required: true })}
              error={errors.id}
              helperText={errors.id?.message}
              variant='standard'
              placeholder='ユーザーIDを入力してください'
              fullWidth
            />
            <TextField
              type='password'
              name='password'
              {...register('password', { required: true })}
              error={errors.password}
              helperText={errors.password?.message}
              variant='standard'
              placeholder='パスワードを入力してください'
              fullWidth
            />

とりあえずこんな感じで、値がない場合はのみフォームを赤くするように設定。
(うまくhelperText出てないけど一旦無視)

挙動としてはこんな感じ

スクリーンショット 2023-01-28 20.48.46.png

zod

項目に対しての簡単な Validation は上でできたいので、zod を用いて詳細な Validation をかけていきましょう。

npm install zod で zod のインストールを行いましょう。

import { z } from "zod";

/**
   * zod での Validation
   */
  const FormData = z.object({
    id: z.string().email("メアドじゃない"),
    password: z
      .string()
      .min(8, "8文字以下だ")
      .max(32, "32文字以上だ")
      .regex(/^(?=.*?[a-z])(?=.*?\d)[a-z\d]{8,100}$/i, "PWに半角英数字入れて"),
  });

onSubmit 時点でvalidation を追加してみる。

import { z, ZodError } from "zod";

  /**
   * 登録時の処理を関数化
   * @param  data formから受け取る値
   */
  const onSubmit = (data) => {
    try {
      FormData.parse(data);
      // アラートで結果出してみる (見やすいようにJSON 形式にする)
      alert(JSON.stringify(data));
    } catch (e) {
      if (e instanceof ZodError) {
        alert(JSON.stringify(e.flatten().fieldErrors));
      } else {
        console.log(e);
      }
    }
  };

挙動確認

失敗

  • ID: aaaaaa
  • PW: aaaaaa
    スクリーンショット 2023-02-23 21.15.23.png

失敗

  • ID: aaaaa@gmail.com
  • PW: aaaaaa

スクリーンショット 2023-02-23 21.17.48.png

成功

  • ID: aaaaa@gmail.com
  • PW: aaaaa12345

スクリーンショット 2023-02-23 21.19.10.png

あとがき

今回は Project を typeScript化 していないですが無理やり、Validation として zod を使用してみました。
正直今回のケースだと、 react-hook-form 標準装備の Validation で十分だったかな。
ただ、 zod 自体は非常に直感的でわかりやすいものでした。

zod が本領発揮するのは TypeScript の プロジェクトで複雑な Schema の型のやり取りなどかなと感じました。
Zod を使用することで 型安全な開発ができるので、最近の流行りというのも納得ですね、何よりわかりやすかったです。

じゃあまた ˙︶˙)ノ"マタネー

0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?