npm install react-hook-form
または
yarn add react-hook-form
import { useForm } from 'react-hook-form';
// React Hook Form
const {register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data:any) => {
alert('form送信されました');
console.log(data);
}
useForm() には様々なオプションを渡すことができます
https://react-hook-form.com/api/useform/
useForm({
mode: 'onSubmit', // onChange | onBlur | onSubmit | onTouched | all = 'onSubmit'
reValidateMode: 'onChange',
defaultValues: {},
resolver: undefined,
context: undefined,
criteriaMode: "firstError",
shouldFocusError: true,
shouldUnregister: false,
shouldUseNativeValidation: false,
delayError: undefined
})
useForm() して返ってくる handleSubmitに (バリデーションOKの時の関数,バリデーションNGの時の関数) を渡します
handleSubmit(SubmitHandler, SubmitErrorHandler)
フォーム の部品の作り方には2つ方法があります
引用 : react-hook-formでregisterとControllerのどちらを使うか - mrsekut-p
・useForm の registerを使って、<input {...register('hoge')} />とする (input , text , MUIの TextField に使用できます )
・useForm のcontrolと <Controller name='hoge' control={フォーム部品コンポーネント }> を使う (上記以外の複雑なコンポーネントはこちらを使用します)
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('company', { required: true, minLength: 4 })} placeholder="株式会社○○" />
{errors.company?.type === "required" && <div className="err_message" id="company_err">会社名は必須です</div>}
{errors.company?.type === "minLength" && <div className="err_message" id="company_err">会社名は4文字以上を入力してください</div>}
<input type="submit" />
</form>
);
<input type="email" placeholder="user@server.xxx"
{...register("email", {
required: "入力必須です",
pattern: {
value: /\S+@\S+\.\S+/,
message: "メールアドレスが不完全です"
}
})}
/>
{errors.email && <div className="err_message">{errors.email.message}</div>}
https://react-hook-form.com/jp/api#register
バリデーションの記述をYupでまとめるには次のように記述します
npm install @hookform/resolvers yup
または
yarn add @hookform/resolvers yup
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';
const validationSchema = Yup.object().shape({
firstName: Yup.string()
.required('First Name は必須です'),
lastName: Yup.string()
.required('Last Name は必須です'),
});
const formOptions = { resolver: yupResolver(validationSchema) };
const { register, handleSubmit, reset, formState } = useForm(formOptions);
const { errors } = formState;
<form onSubmit={handleSubmit(onSubmit)}>
<input type="text" {...register('firstName')} className={`form-control ${errors.firstName ? 'is-invalid' : ''}`} />
<div className="invalid-feedback">{errors.firstName?.message}</div>
</form>
name="firstName" は記述しなくてokです。
外部からフォームの値を変更するには以下の2つの方法を使用します。
( なお、useState は使用できません )
( MUI を使用している場合でも問題なくこちらの方法で値を流し込むことができます。(ただしバージョンが古いとうまく動作しないのでできるだけ新しいバージョンにアップデートしましょう。
過去にreact-hook-form@7.3.0 ではうまく動作しませんでした。)
次の二箇所にデータを流し込む命令をセットします
// ● SWR
const fetcher = (url: string) => axios(url)
.then((res) => {
reset(res.data); // 1. axiosでデータ取得時にデータをフォームに反映(Re-render)
return res.data
});
const { data, error, mutate } = useSWR(`http://localhost:8000/api/news/1`, fetcher);
// ● useForm
const formOptions = {
defaultValues: data, // 2. SWRのキャッシュがデータをすでに取得している場合はキャッシュからフォームに反映
};
const { control, register, handleSubmit, reset, formState: { errors } } = useForm(formOptions);
// ● React Hook Form
const { register, handleSubmit, setValue, formState } = useForm(formOptions);
setValueを使用します
// ● SWR
const fetcher = (url: string) => axios(url)
.then((res) => {
// 最初に1度だけフォームに値をセット
const data = res.data;
Object.keys(data).forEach(function (k) {
setValue(k, data[k]);
});
return res.data
});
const { data, error, mutate } = useSWR(`http://localhost:8000/api/news/${params.id}`, fetcher);
// swrによるfetchエラー時
if (error) return <div>failed to load</div>
{...register('hoge')} の記述が抜けている可能性がありますチェックしましょう。
<input type="text" id="hoge" {...register('hoge')} />
自作関数を使う場合このように記述できます
function myPasswordCheck(){
return false
}
.test(
"mypassword",
"パスワードが間違っています",
myPasswordCheck
)
https://github.com/jquense/yup/issues/503
createError() を返せばokです。createErrorファンクション自体は渡してあげる必要があります。
return createError({
message: `パスワードは半角英字、数字、記号を組み合わせた 8文字以上で入力してください (${password})`,
});
https://react-hook-form.com/api/useformstate
https://qiita.com/bluebill1049/items/f838bae7f3ed29e81fff
yarn add @hookform/devtools
import { DevTool } from '@hookform/devtools';
jsx
<DevTool control={control} placement="top-left" />
<form onSubmit={handleSubmit(onSubmit, onError)}>
.............
</form>
公式サンプル
https://github.com/react-hook-form/react-hook-form/tree/master/examples
React Hook Form 7 - Form Validation Example | Jason Watmore's Blog
jsonによるスキーマ定義をyupに変換する
https://github.com/kristianmandrup/schema-to-yup
yarn add schema-to-yup
onClick = { () => {
handleSubmit(onSubmit)()
}}
https://github.com/alibaba/hooks
import { useThrottleFn } from 'ahooks'
const { run: throttledHandleSubmit } = useThrottleFn(
() => {
handleSubmit(onSubmit)()
},
{ wait: 2000 }
)
onClick = { throttledHandleSubmit }