logo

React でフォームバリデーションの実装方法 (Joi Validation)

REACT でフォームバリデーションの実装方法 (JOI VALIDATION)...
プログラミング
目次
  • Joi Validation とは?

  • React VITE のセットアップ

  • ファイル構成

  • プロジェクト内容

  • CSS ファイル

  • App.jsx

  • Reactでフォームバリデーションを実装する方法について、便利なライブラリを使って詳しく解説していきます。

    フォームバリデーションは、ウェブアプリケーションにおいてユーザーからの入力が期待する形式であることを保証する重要なプロセスです。

    このプロセスを効率的に管理するため、以下のライブラリを紹介します。

    • Joi: Airbnb によって開発された、強力で信頼性の高いバリデーションライブラリです。
    • react-hook-form: 効率的で柔軟なフォームハンドリングを可能にするReactライブラリです。
    • @hookform/resolvers: Joiなどのバリデーションライブラリとreact-hook-formを簡単に統合できるアダプターです。
    • react-bootstrap (オプション): スタイリッシュなフォームコンポーネントを提供するUIフレームワークです。

    Joi Validation とは?

    form validation フォームバリデーション

    公式ドキュメント

    Joiは、データのバリデーションを容易にし、開発プロセスを加速させることができるライブラリです。

    特に、フォームデータの検証において、その柔軟性と拡張性は大きなメリットを提供します。
    Joiを使用することで、様々なデータ型に対する複雑なバリデーションルールを簡単に定義し、実装することができます。

    特に、react-hook-formとJoiを組み合わせることで、コードの冗長性を減らし、フォームのバリデーションロジックを簡潔かつ効率的に実装できるようになります。

    さらに、react-bootstrapをオプションとして取り入れることで、フォームの見た目を簡単にカスタマイズして、ユーザーにとって良いUIを提供することができます。

    この記事のReactでのフォームバリデーションを使用して、信頼性の高いウェブアプリケーション開発ができるかと思います。

    React VITE のセットアップ

    まずは React VITE をインストール

    npm create vite@latest

    bootstrap のインストール(オプション)

    npm i react-bootstrap bootstap 

    react-hook-form と Joi をつなげる @hookform/resolvers。

    npm i joi react-hook-form @hookform/resolvers

    ファイル構成

    src
      -- App.tsx
      -- App.css

    プロジェクト内容

    Joi form validation フォームバリデーション

    デモサイト

    CSS ファイル

    コードを開く
    h2 {
    	text-shadow: 0px 15px 5px rgba(0, 0, 0, 0.1),
    		10px 20px 5px rgba(0, 0, 0, 0.05),
    		-10px 20px 5px rgba(0, 0, 0, 0.05);
    }
    
    body {
    	background-color: rgba(0, 0, 0, 0.2);
    }
    
    input[type="text"],
    input[type="file"] {
    	box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
    }
    
    input[type='range']::-webkit-slider-runnable-track {
    	height: 2.1rem;
    	border: 1px solid lightgray;
    	box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
    }
    
    input[type='range']::-webkit-slider-thumb {
    	margin-top: 0rem;
    	width: 2rem;
    	height: 2rem;
    	background: black;
    }

    App.jsx

    バリデーションの設定は下記の通りです

    • moodScore: mood の状態が1の状態では送信不可
    • why: Reason のフォームが空の状態、もしくは3文字以内 & 200文字以上では送信不可
      const schema = Joi.object({
        moodScore: Joi.number().min(1).max(4).required(),
        why: Joi.string().min(3).max(200).required()
      });

    react-hook-form の watch で、 useEffectを使うことなく状態を監視できます。

      const { handleSubmit, control, watch, formState: { errors } } = useForm({
        resolver: joiResolver(schema),
        defaultValues: {
          moodScore: 2, // 初期値
          why: "Feeling a bit peckish 🍔" // 初期値
        }
      });
      // watchを使用してmoodScoreの値を監視
      const watchMoodScore = watch('moodScore');
    
    return (
    ...
    ...
       {/*  watchMoodScoreの値に応じて絵文字を表示  */}
       <div className="text-center my-3" style={{ fontSize: "3rem" }}>
         {scoreToEmoji(Number(watchMoodScore))}
       </div>
    コードを全部開く
    import { useForm, Controller } from 'react-hook-form';
    import { joiResolver } from '@hookform/resolvers/joi';
    import Joi from 'joi';
    import { Button, Form } from 'react-bootstrap';
    import './App.css';
    import "bootstrap/dist/css/bootstrap.min.css";
    
    // Joiのバリデーションをスキーマを作成
    const App = () => {
      const schema = Joi.object({
        moodScore: Joi.number().min(1).max(4).required(),
        why: Joi.string().min(3).max(200).required()
      });
    
      // useFormフックを使用してフォームの状態を管理
      const { handleSubmit, control, watch, formState: { errors } } = useForm({
        resolver: joiResolver(schema),
        defaultValues: {
          moodScore: 2, // 初期値
          why: "Feeling a bit peckish 🍔" // 初期値
        }
      });
    
      // watchを使用してmoodScoreの値を監視
      const watchMoodScore = watch('moodScore');
    
      // moodScoreに応じて絵文字を返す関数
      const scoreToEmoji = (score) => {
        switch (score) {
          case 0: return "😭";
          case 1: return "😔";
          case 2: return "😐";
          case 3: return "🙂";
          case 4: return "😃";
          default: return "🤷‍♂️";
        }
      };
    
      // フォームのデータを送信する関数
      async function onSubmit(data) {
        try {
          window.alert(data.why);
        } catch (error) {
          console.error(error);
        }
      }
    
      return (
        <div className='w-50 mx-auto mt-5'>
          <h2 className="text-center">Your Mood Today</h2>
          <Form onSubmit={handleSubmit(onSubmit)}>
            <Form.Group>
              <Form.Label>Mood Indicator</Form.Label>
              <Controller
                name="moodScore"
                control={control}
                render={({ field }) => <Form.Range min={0} max={4} {...field} />}
              />
              {/* バリデーションのエラーメッセージを表示 */}
              {errors.moodScore && <Form.Text className="text-danger">悲しい気持ちをシェアしないでください</Form.Text>}
    
              {/*  watchMoodScoreの値に応じて絵文字を表示  */}
              <div className="text-center my-3" style={{ fontSize: "3rem" }}>{scoreToEmoji(Number(watchMoodScore))}</div>
    
            </Form.Group>
            <Form.Group>
    
              <Form.Label>Reason</Form.Label>
              <Controller
                name="why"
                control={control}
                render={({ field }) => <Form.Control as="textarea" rows={3} {...field} />}
              />
              {/* バリデーションのエラーメッセージを表示 */}
              {errors.why && <Form.Text className="text-danger">{errors.why.message}</Form.Text>}
            </Form.Group>
            <Button variant="success" type="submit" className="mt-4" >Share Your Mood</Button>
          </Form>
        </div>
      );
    };
    
    export default App;
    

    人気記事

    メルボルン移住(ワーホリ)を検討している方へ
    オーストリア
    メルボルン移住(ワーホリ)を検討している方へ
    メルボルンで絶対に行きたい場所10選
    オーストリア
    メルボルンで絶対に行きたい場所10選
    『ネイティブ監修』 オーストラリア厳選スラング30
    英語
    『ネイティブ監修』 オーストラリア厳選スラング30
    海外のWEBエンジニア特化スクールの費用や授業内容や費用など完全解説(オーストラリア・メルボルン)
    オーストリア
    海外のWEBエンジニア特化スクールの費用や授業内容や費用など完全解説(オーストラリア・メルボルン)
    • Kazu

      Kazu

      オーストラリア在住歴7年。現地で英語学習後に日本語教師 → 工場就職 → 海外WEB開発ディプロマを取得→フリーランス。現在は余った時間をプログラミング&ブログに費やして生きています。

    136