【ReactNative】react-hook-formでFCでフォームを使う
はじめに
React
やReactNative
を開発していて避けられないのがForm
だと思います。
このあたりはいくつかライブラリがあり、有名どころを使っておけばそんなに苦労はしない印象ですが、Hooks
をゴリゴリ使っているとなると選択肢は狭まってきます。
今回はHooks
を中心にコンポーネントを作成している場合に組み込みやすいreact-hook-form
を紹介していきます。
react-hook-formとは
公式を参照すると
高性能で柔軟かつ拡張可能な使いやすいフォームバリデーションライブラリ。
と謳われており、少ない記述量で高速で動作するフォームライブラリです。
フォーム関連の他ライブラリと動作速度やマウント数の比較があります。
React Hook Form
- マウント数: 1
- 変更コミット数: 1
- 合計時間: 1800ms
Formik
- マウント数: 6
- 変更コミット数: 1
- 合計時間: 2070ms
Redux Form
- マウント数: 17
- 変更コミット数: 2
- 合計時間: 2380ms
たしかにこれを見る分には最小限のマウントで高速に動作するようです。
インストール
下記コマンドでインストールを行います。
yarn add react-hook-form
使い方
最もオーソドックな使い方は以下の通りです。
useForm
が用意されているため、useState
やuseEffect
あたりをよく使っている場合は挙動が理解しやすいのかなと思います。
import React from "react";
import { useForm } from "react-hook-form";
// フォーム内のフィールド情報を定義
type Inputs = {
example: string,
exampleRequired: string,
};
const App: React.FC = () => {
const { register, handleSubmit, watch, errors } = useForm<Inputs>();
const onSubmit = data => console.log(data);
// watch()で監視したいフィールドの値を指定
console.log(watch("example"));
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* registerを使うことで入力した値をフックに登録 */}
<input name="example" defaultValue="test" ref={register} />
{/* 必須や入力ルールを指定することも可能 */}
<input name="exampleRequired" ref={register({ required: true })} />
{/* errorsには入力チェックで失敗した値が入ってくる */}
{errors.exampleRequired && <span>This field is required</span>}
<input type="submit" />
</form>
);
}
上記にある通り、関数コンポーネントの中にすんなり組み込むことができるため使い勝手がいい印象です。
ReactNativeにも対応
さらにreact-hook-form
はReactNative
で使用することもできます。
React
の場合と異なりinput
に対応するコンポーネントを自由に指定できますが、記述量は多くなります。
下記サンプルのようにController
コンポーネントを配置し、render
に実際に表示させるコンポーネントを指定します。
import React from 'react';
import {Button, Text, TextInput, View} from 'react-native';
import {useForm, Controller} from 'react-hook-form';
// フォームの値を定義
type FormData = {
name: string;
zipCode: string;
};
const App: React.FC = () => {
const {control, handleSubmit, errors} = useForm<FormData>();
// submit時処理
const onSubmit = (data: FormData) => {
console.log(data);
};
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}}>
<View style={{flex: 0.2, alignItems: 'flex-end'}}>
<Text>名前</Text>
</View>
<View style={{flex: 0.8}}>
<Controller
control={control}
render={({onChange, onBlur, value}) => (
<TextInput
style={{
borderBottomWidth: 1,
borderBottomColor: '#ccc',
width: '80%',
fontSize: 20,
margin: '4%',
}}
placeholder="○○太郎"
onBlur={onBlur}
onChangeText={(value) => onChange(value)}
value={value}
/>
)}
name="name"
rules={{
required: true,
maxLength: 10,
}}
defaultValue=""
/>
{errors.name && errors.name.type === 'required' && (
<Text style={{color: 'red'}}>Nameは必須です。</Text>
)}
{errors.name && errors.name.type === 'maxLength' && (
<Text style={{color: 'red'}}>
Nameは10文字以内で入力してください。
</Text>
)}
</View>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}}>
<View style={{flex: 0.2, alignItems: 'flex-end'}}>
<Text>郵便番号</Text>
</View>
<View style={{flex: 0.8}}>
<Controller
control={control}
render={({onChange, onBlur, value}) => (
<TextInput
style={{
borderBottomWidth: 1,
borderBottomColor: '#ccc',
width: '80%',
fontSize: 20,
margin: '4%',
}}
placeholder="000-0000"
onBlur={onBlur}
onChangeText={(value) => onChange(value)}
value={value}
/>
)}
name="zipCode"
rules={{
pattern: /^\d{3}-\d{4}$/,
}}
defaultValue=""
/>
{errors.zipCode && errors.zipCode.type === 'pattern' && (
<Text style={{color: 'red'}}>
郵便番号のフォーマットが不正です。
</Text>
)}
</View>
</View>
<Button title="Submit" onPress={handleSubmit(onSubmit)} />
</View>
);
};
export default App;
実行結果
validation
もしっかりかかってることが分かりますね。
まとめ
今回はreact-hook-form
について紹介しました。
Hooks
が追加されて以降、新しく作るアプリはなるべくHooks
を使ってコンポーネントを書くようにしていますが、そういった場合に扱いやすいライブラリとなっています。
Discussion