【React】制御コンポーネントと非制御コンポーネント

## はじめに
Reactのフォーム実装に関する「制御コンポーネント」と「非制御コンポーネント」についてまとめます。

## 制御コンポーネント
制御コンポーネントとは、フォームの入力値をReactコンポーネント（state）で扱うコンポーネントのことです。
メリットとしては、常に値にアクセスできるため、 **ユーザが入力中にバリデーションを実施する** 、といったリアクティブなフォームを作成できます。
デメリットとしては、入力値が更新されるたびに **再レンダリングが発生します**。

### 制御コンポーネントの実装例

```tsx
import { useState } from "react";

export const Controlled = () => {
  const [inputValue, setInputValue] = useState<string>("");

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;

    // 入力中にもバリデーション
    if (value.length <= 10) {
      console.log("10文字以上で入力してください");
    }

    setInputValue(value);
  };

  const handleSubmitClick = () => {
    if (inputValue.length <= 10) {
      return;
    }
    console.log(inputValue);
  };

  return (
    <>
      <p>制御コンポーネント</p>
      <input type="text" value={inputValue} onChange={handleChange} />
      <button onClick={handleSubmitClick}>送信</button>
    </>
  );
};
```

## 非制御コンポーネントとは
非制御コンポーネントとは、フォームの入力値をDOMで扱うコンポーネントのことです。
`useRef`とinput要素の`ref`属性を使用します。
メリットとしては、stateを経由しないため、入力値の更新毎に **再レンダリングが発生しません**。
デメリットとしては、必要なタイミング（submit時など）でDOMから入力値を取得するため、入力中にバリデーションを実施する、といった実装が難しいことが挙げられます。

### 非制御コンポーネントの実装例
```tsx
import { useRef } from "react";

export const Uncontrolled = () => {
  const ref = useRef<HTMLInputElement>(null);

  const handleSubmitClick = () => {
    const value = ref.current?.value;

    // submit時にバリデーション
    if (value && value.length <= 10) {
      console.log("10文字以上で入力してください");
      return;
    }

    console.log(value);
  };

  return (
    <>
      <p>非制御コンポーネント</p>
      <input type="text" ref={ref} />
      <button onClick={handleSubmitClick}>送信</button>
    </>
  );
};
```

## 両者の比較とReact Hook Form
React公式では制御コンポーネントの使用を推奨しています。
理由としてはメリットで挙げた「入力中のバリデーション」など、できることが多いためです。
ただ、パフォーマンスへの懸念を考えると非制御コンポーネントを使いたくなるかと思います。

このような場合、React Hook Formを使うことで両者のメリットを享受できます。
React Hook Formは非制御コンポーネントを採用しており、`ref`属性に`register`を渡すことで、フォームの実装ができます。
基本的な使い方を以下の記事にまとめました。
[React Hook FormとZodの基本的な使い方](https://qiita.com/y-suzu/items/952d417f0853341a97df)

また、なぜ非制御コンポーネントであるにも関わらず、リアクティブなフォームを実装できるのか？という疑問が出てくるかと思います。
これについては以下の記事に詳細にまとめられていたため、引用させていただきます。
[React Hook Formは非制御コンポーネントからどうやって変更を検知しているのか](https://tech.commmune.jp/entry/2021/01/21/085959)

## 参考記事
https://ja.legacy.reactjs.org/docs/forms.html#controlled-components

https://ja.legacy.reactjs.org/docs/uncontrolled-components.html

https://goshacmd.com/controlled-vs-uncontrolled-inputs-react/

https://scrapbox.io/teamlab-frontend/%E5%88%B6%E5%BE%A1%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%A8%E9%9D%9E%E5%88%B6%E5%BE%A1%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%82%92%E6%AD%A3%E3%81%97%E3%81%8F%E7%90%86%E8%A7%A3%E3%81%97%E3%80%81%E9%81%A9%E5%88%87%E3%81%AA%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%97%E3%81%BE%E3%81%97%E3%82%87%E3%81%86

https://uga-box.hatenablog.com/entry/2020/09/24/000000

https://tech.commmune.jp/entry/2021/01/21/085959

## 採用のお知らせ
株式会社Relicでは、エンジニア・デザイナーを積極的に採用中です。
またRelicでは、地方拠点がありますので、U・Iターンも大歓迎です！🙌
少しでもご興味がある方は、Relic採用サイトからエントリーください！

https://relic.co.jp/recruit?utm_source=qiita&utm_medium=article&utm_campaign=qiita_article

https://relic.co.jp/categories/job_4?utm_source=qiita&utm_medium=article&utm_campaign=qiita_article