react-hook-form #1 stateまみれのcomponentを改善したい

目的

reactのform componentを書くときに入力値をstateで管理して、stateまみれのcomponentを作ってしまって可読性を下げてしまうことってありませんか? 例えば、こんな感じ。

import {NextPage} from 'next';
import {useState} from 'react';

const StartPage: NextPage = () => {
  const [example, setExample] = useState('');
  const [exampleRequired, setExampleRequired] = useState('');

  return (
    <form>
      <input name="example" value={example} onChange={(e): void => setExample(e.target.value)} />
      <input
        name="exampleRequired"
        value={exampleRequired}
        onChange={(e): void => setExampleRequired(e.target.value)}
      />
      <input type="submit" />
    </form>
  );
};

export default StartPage;

項目数が少ないと上記のようなコードでも大丈夫ですが、項目数が増えて、さらに、項目ごとのエラーをstateで管理するってなったら、state地獄になってしまいますよね。
stateを乱立させずに、入力値を管理できるようにしたい。
そんな時に使用するのが、react-hook-formです。

導入手順

導入の仕方はすごく簡単で、以下のライブラリをinstallするだけです。ほかに依存しているライブラリなどはありません。

npm install react-hook-form

改善

react-hook-formを導入すれば、目的で書いたよう例題はこのように改善されます。

import {NextPage} from 'next';
import {useForm} from 'react-hook-form';

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

  const onSubmit = (data: any): void => console.log(data);

  // watch input value by passing the name of it
  console.log(watch('example'));

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* register your input into the hook by invoking the "register" function */}
      <input defaultValue="test" {...register('example')} />

      {/* include validation with required or other standard HTML validation rules */}
      <input {...register('exampleRequired', { required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}

      <input type="submit" />
    </form>
  );
};

引用元#exaple

react-hook-form.com

ポイント

  • exampleやexapleRequiredなどの個別のstateを用意せずに済む。
  • useFormのhooksでformのhande処理、項目のエラーなど様々なものが用意されている。

簡単な解説

まず、初めに、useFormでreact-hook-formを使用する準備を行います。

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

register

registerはinputタグに使用します。使用する際に名前(exaple)を付与して、以後はその名前でvalue値を取得できるようになります。

<input defaultValue="test" {...register('example')} />

hadlesumit

formのonSubmitの処理をhadleするのに使用します。

<form onSubmit={handleSubmit(onSubmit)}>

watch

inputで付与した名前に対して、値を監視することができます。

console.log(watch('example'));

formState

エラーなどのformに関する値を様々に管理しています。

  {errors.exampleRequired && <span>This field is required</span>}

実際に画面を動かしてみた

値を入力して送信ボタンを押したところ、consoleにexampleとexampleRequired の値が確認できる。

TypeScriptでFormの型を指定する場合

typeを作成し、useFormのジェネリクスに型を指定すれば、Formのデータ型を指定することができ、registerでtype以外の名前を使用することができなくなる。

type FormType = {
  example: string;
  exampleRequired: string;
};

const StartPage: NextPage = () => {
  const {
    register,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm<FormType>();

  const onSubmit = (data: any): void => console.log(data);

  // watch input value by passing the name of it
  console.log(watch('example'));

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* register your input into the hook by invoking the "register" function */}
      <input defaultValue="test" {...register('example')} />

      {/* include validation with required or other standard HTML validation rules */}
      <input {...register('exampleRequired', { required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}

      <input type="submit" />
    </form>
  );
};

export default StartPage;

まとめ

state管理に苦しまなずに済む。

おススメのライトノベルです。是非、ぽちってください。