controlled input と uncontrolled input
今回の経緯について
会員登録ページにて処理を実装していたところ、こんなエラーが出現しました。
ここでuncontrolledとcontrolledという言葉が出てきたので、調べてみました。
目次
- controlled
- uncontrolled
- まとめ
controlled
controlledとは、直訳すると管理されたという意味があります。
Reactでは、controlledとuncontrolled二つのタイプのinputを作成することが出来ます。
これが、条件分岐などで予期せず入れ替わってしまい、先ほどのエラーが起きてしまうようです。
ここからが本題で、まずcontrolled inputがどういうものなのか、コード等を交えてご紹介します。
controlled inputでフォーム作成時のコード
import { SetStateAction, useState } from "react";
const Form = () => {
const [state, setState] = useState<string>("");
const handleStateChange = (e: { currentTarget: { value: SetStateAction<string>; }; }) => {
console.log(e.currentTarget.value);
setState(e.currentTarget.value);
};
return(
<div>
<label>state</label>
<input
type="text"
value={state}
onChange={handleStateChange}
/>
</div>
)
}
export default Form;
controlled inputの特徴
実際に動かしてみたとき、inputの値は常に管理・監視されています。
handleStateChangeで出力されたログを見るとこんな感じ。
これがcontrolledの1つ目の特徴になります。
これを使って1入力毎にバリデーションをすることもできるようになります。
2つめはformを使って書く必要がない点です。
通常、formの要素を送り、そこから必要な情報を取り出して使用しますが、
controlledではその必要がない(inputを監視し、入力ごとにデータを取得している)為、form要素が無くても上記のように動作します。
useState
controlled inputを作成するにあたり、今回はReact hooksのuseStateを使用しました。
一応ご紹介しますが、既に知っている方は飛ばしてしまって問題ないです。
const [state, setState] = useState<Type>("");
※typeScriptでの例なので、型の設定がされていますが、Reactのみを使用されている場合は型の設定は要りません。
useStateの第一引数として、stateの初期値を設定しますが、
初期値として何も入れないとエラーが起きてしまうのでご注意ください。
//エラー発生
const [state, setState] = useState<string>();
そして、setStateはメソッドであり、これを使用することで、stateの値を変更します。
setState("something")// state="something"
uncontrolled
uncontrolledは先ほど少し話に出しましたが、従来のformを使って値を送る方法です。
React hooksでは、useRefを用いてこれを再現します。
import { useRef } from "react";
const Form = () => {
const ref = useRef<HTMLInputElement>(null)
const submitHandler = (e: React.ChangeEvent) => {
e.preventDefault()
console.log(ref.current?.value)
};
return(
<form onSubmit={submitHandler}>
<input type="text" ref={ref}/>
<button type="submit">ボタン</button>
</form>
);
}
export default Form;
ボタン押下時に動作し、ログにはこのように出ます。
普段React以外を使って開発される方はよく見る機会のある形かと思います。
ボタンを押下し、formが送られる以外に管理・監視しないので、uncontrolledと呼ばれるわけですね。
typeScriptを使う上での注意点
submitHandlerでは下記のように「?」を使ってます。
console.log(ref.current?.value)
これは「null」を許容する為に使用し、付けないと「オブジェクトがnullになる可能性があります。」というようなエラーが出現しますので、ご注意ください。
「?」はifみたいなものだと思ってください。
useRef
uncontrolled inputを作成するにあたり、今回はReact hooksのuseRefを使用しました。
こちらも一応ご紹介しますが、既に知っている方は飛ばしてしまって問題ないです。
const ref = useRef<Type>(null)
typeScriptを使用する場合は上記のように書きますが、Reactのみの場合は、下記のように書きます。
const ref = useRef()
そして、どのようにして値を取得するかですが、inputのrefプロパティにセットしてあげましょう。
<input type="text" ref={ref}/>
あとは、formを何かしらのアクション発生時に送信してあげれば、先ほどのように取得出来るといった流れになります。
typeScriptでuseRefを使用時の型についてのエラーを下記で説明しております。良ければご覧ください。
まとめ
最後にcontrolledとuncontrolledについてまとめます。
controlledとは管理された状態。つまり、変化がある度に取得します。
uncontrolledとは、管理されていない状態で、結果だけを取得します。
仕事をする上で、工程毎に評価するか、結果だけで評価するかみたいな違いですね。
工程毎に評価する事により、その工程上で問題があれば指摘出来たりするわけです。
また、controlledでは管理を別々にすることが出来るので、
1作業目最中に評価、2作業目最中に評価・・・
といったようにすることができます。
例を挙げると、メールとパスワードを入力するフォームがあったとします。
メールを打ってる際にメール側をチェック、パスワードを打つ際にパスワードをチェック
とすることにより、差し戻しを少なく出来ます。
ログイン時と登録時で使い分けるなど、この違いを何をするかで上手く使い分けていきたいですね。
ここまで読んで下さり、ありがとうございました。
参考にしたサイト
Discussion