😀

React Hook Formで独自の複数選択を実装する

2023/10/25に公開

Multiple Selection In ReactHookForm

前回書いたタグ入力のコンポーネントをReact Hook Formで組み込んだメモです。
簡易実装は以下になります。

https://codepen.io/ta_kasy/pen/XWObjmB

環境

  • React 18.2.0
  • React Hook Form 7.47.0
  • TailwindCSS 2.2.19
  • clsx 2.0
  • TypeScript

実装

独自の複数選択を処理するにはControllerを使うのが良さそうです。
他にもReact-SelectやAntD、MUIなどの外部制御コンポーネントとの連携を容易してくれます。

Propsの定義

普通のフォームは入力項目が複数あると思いますが今回はとりあえずタグ入力のみのフォームとして定義しています。

App.tsx
type TagForm = {
    tags: string[]
}

フォーム

Controllerは使用したい外部コンポーネントをラップして利用します。(renderから返す)
必要な項目はnamecontrlrenderになります。
controlはどのuseFormかを登録するものです。
renderの処理は特に記述するような内容ではありませんが変更を検知してsetValue()で値の更新を行います。
Controllerでは他にもdefaultValuerulesなども渡すことができます。
詳細はドキュメントを確認してください。

https://react-hook-form.com/docs/usecontroller/controller

App.tsx

const App: React.FC = () => {
  const [formValues, setFormValues] = React.useState({})
  const {control, handleSubmit, setValue, formState: { errors }} = useForm<TagForm>()
  
  const onSubmit = (form: TagForm) => {
    //APIへ送信するなどの処理
    console.log(form)
    setFormValues(form)
  }

  return <form onSubmit={handleSubmit(onSubmit)}>
    <Controller
      name="tags"
      control={control}
      defaultValue={["hoge"]}
      rules={{required: true}}
      render={({field: { value }} ) => {
        return (
            <TagsInput tags={value} 
                       onChangeTags={(tags) => setValue('tags', tags)} 
            />
        )
      }}
    /> 
    {errors.tags && (<div className={"text-red-500"}>tag is required.</div>)}
    <button type="submit" className={"mt-2 bg-green-500 text-white py-2 px-4 text-m rounded"}>送信する</button>
    <div className={"mt-2 p-4 bg-gray-100"}>{JSON.stringify(formValues)}</div>
  </form>
}

ReactDOM.render(<App />,
document.getElementById('root'));

最後に

いかがだったでしょうか。
参考になったよっという方はぜひいいねよろしくお願いします!!

Discussion