React Hooksの基礎



業務でReact(Next.js × TypeScript)を使う機会があったため、メモとして書き残しておきます。


*環境

  • MacOS
  • react :18.2.0
  • react-hook-form:7.51.0
  • typescript:5.3.3


*Next.jsプロジェクトの作成方法

nvmのインストール

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.4/install.sh | bash

// Nodeバージョンをあげないと起動ができなかったため下記コマンドを実行
$ nvm install v18.17.0
$ nvm use 18.17.0
$ node -v
v18.17.0

起動

$ npm run dev

※起動しないときは、下記を実施する

  1. 下記フォルダーを削除
.next
node_modules
  1. 再インストール
$ npm install
  1. 再起動
$ npm run dev

> next-form@0.1.0 dev
> next dev
▲ Next.js 14.1.0
- Local:  http://localhost:3000


*参考


*React Hooks

  • React16.8以降から追加された機能
  • 状態管理などの機能を冗長なコードを書かずに使える
  • 関数コンポーネントでも状態管理の機能を使うことができる
  • Hooksの機能をカスタムフックとして共通化することも可能(コードの煩雑化を防げる)


*React Hook Form

  • Hooksの機能を利用したフォームライブラリ
  • 入力フォームの状態を容易に管理することができる
  • 入力値のバリデーションチェックも容易にできる


*useState

  • Stateの値保持と更新をするためのHooks
  • 画面に動的な値を表示させるときなどに使用
  • 最もよく使われる機能
  • 基本的な使い方:const [{ 値を保持する変数 }, { 値を更新するメソッド名 }] = useState<型>({ 初期値 })
const [name, setName] = useState< string >(“”)


*useEffect

  • レンダリングの後に処理を実行させる、第二引数を与えるとその値が更新されたときに実行される(初期表示時に行たい処理など)


*useForm

  • 入力された値を管理し、入力値のバリデーションを容易にするためのHooksを使ったライブラリ
  • 入力項目に対しては基本的にこれを使用する
  • TypeScriptと組み合わせて使うことで型バリデーションを実現
  • 初期値の設定も可能
  • 入力項目が複数ある場合も、1つのuseFormで項目全体/個別の管理ができる
  • 基本的な使い方: const { 使いたい関数 } = useForm< 入力フォームの型 >()
export type inputForm = {
  firstName: string;
  lastName: string;
}
const {register, watch} = useForm<InputForm>()


*register

  • 入力項目にバリデーションルールを適用するためのuseForm関数
  • 第1引数に管理したい項目名、第2引数にオブジェクト形式でバリデーションルールを指定する
  • バリデーションルールは必須/文字数などの指定が可能
  • 基本的な使い方:
    <input type=“text” {…register(“name”), {required: “返却させたいエラーメッセージ”, maxLength: 10, minLength: 1}} />
<div className="mt-2">
  <input
    type="text"
    id="lastName"
    className="text-sm"
    {...register("lastName", { required: "姓を入力してください" })}
  />
</div>


*watch

  • 入力値をリアルタイムで監視し、変更があった場合も動的に変更後の値を参照することができるuseForm関数
  • useForm関数で値を参照する機能にgetValueもあるが、こちらは動的に値を変更することができない
  • 入力値が変更される度に画面全体が再描画されるため、不要なレンダリングがされないよう注意が必要


*handleSubmit

  • フォームが送信されるときに実行関数を指定できるuseForm関数
  • バリデーションエラーがある場合はフォームを実行させないようにする(エラーがない場合に指定した関数が実行される)


*formState

  • フォームの情報を保持するuseForm関数
  • バリデーションエラーの有無、値の変更有無を管理することができる
  • ボタン押下時のバリデーション実行でエラーメッセージを表示させるようにしているが、validateとwatchを使うことでリアルタイムエラーを表示させることも可能


*FormProvider

  • 親で定義したuseFormを子コンポーネントで使用できるようにする機能
  • 子コンポーネントを FormProvider で囲い、子コンポーネント内で useFormContext を呼び出すことで register などを使うことができるようになる。
import { FormProvider, useForm } from "react-hook-form";
import { Name } from "./presentations";

export type inputForm = {
  firstName: string;
  lastName: string;
}

const Input: React.FC = () => {
  const methods = useForm<inputForm>({
    mode: "onChange"
  })
  return (
    <FormProvider {...methods}>
      <form>
        <div className="border-b border-gray-900/10 pb-12">
          <h2 className="text-base font-semibold leading-7 text-gray-900">入力画面</h2>
          <p className="mt-1 text-sm leading-6 text-gray-600">登録する情報を入力してください</p>
          <div className="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
            <Name />
          </div>
        </div>
      </form>
    </FormProvider>
  )
}
...
export  const  Name:  React.FC  =  ()  =>  {
  const  {  register,  formState:  {  errors  }  }  =  useFormContext<inputForm>()
  
...


*useContext

  • Propsを使わず親コンポーネントから子/孫コンポーネントに値を連携することができる(認証情報の管理など


*useMemo

  • 関数が実行した値を保持しておき変更がなかったら以前の値を使い回す(時間がかかる計算処理など)


*useCallback

  • 呼び出しの結果をキャッシュしておき、再度同じ入力が発生したときにキャッシュを再利用することができる(不要なレンダリングを防ぐ目的で使用する)


*useRef

  • DOMを参照して要素にアクセスすることができる
  • レンダリング後も値を保持することができる(useStateはレンダリング後に初期化されてしまうがuseRefを使うと値を保持できる)
const value = useRef("")
// 値を参照
console.log(value.current)
// 値を更新
value.current = "update"


*最後に

各機能の詳細な使い方については、別記事にまとめたいと思います。

Previous
Next Post »

人気の投稿