1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【React】React Hook Formを使ってリファクタリングしてみる

Last updated at Posted at 2023-06-21

はじめに

とある日のこと

私「いやー、仕様変更に伴ってフォームの項目が増えてきましたね...」

メンバー「各項目に対して状態変数を宣言しているのでコード量がすごいことになってます」

私「どうにかして上手く書けないですかね」

メンバー「なんかReact Hook Formというのを使えば上手く書けるみたいですね」

私「ちょっと触ってみますか」

本題

React Hook Formとはフォームの状態管理やバリデーションを作成することができるライブラリです。

React Hook Formを使わない場合

image.png

コードを表示する
import { FormLabel, Input, Button, VStack, Text } from '@chakra-ui/react'
import React, { ChangeEvent, useState } from 'react' 

function App() {
 const [name, setName] = useState("")
 const [nameErr, setNameErr] = useState("")
 const [isNameErr, setIsNameErr] = useState(false)

 const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  console.log(name)
 }
 
 const onChangeName = (e: ChangeEvent<HTMLInputElement>) => {
  if (e.target.value.length === 0) {
    setNameErr("名前は必須です");
    setIsNameErr(true);
  } else {
    setNameErr("");
    setIsNameErr(false);
  }
  setName(e.target.value)
 }

 return (
   <VStack>
     <form  onSubmit={(e) => handleSubmit(e)}>
       <VStack>
         <FormLabel htmlFor="名前">First name</FormLabel>
         <Input id="name" type='text' onChange={(e) => onChangeName(e)} isInvalid={isNameErr}/>
         {isNameErr && <Text color="red.500">{nameErr}</Text>}
         <Button mt={4} colorScheme="teal" type="submit" isDisabled={!(name)}>
           Submit
         </Button>
       </VStack>
     </form>
   </VStack>
 )
}
export default App;

コードでは状態変数や関数をたくさん宣言していますね…
「名前」の状態変数、エラーメッセージの状態変数、バリデートの状態変数の3つを宣言しています。
また、状態によってエラーメッセージを表示させる関数も宣言しています。
入力フォームに新しく項目を追加する度にこれらを宣言していくと凄いことになります。

そこでReact Hook Formを使ってみたいと思います

React Hook Formを使った場合

コードを表示する
import { FormLabel, Input, Button, VStack, Text } from '@chakra-ui/react'
import { useForm } from 'react-hook-form';
 
interface LoginForm {
  name: string;
  password: string;
}

function App() {
const { register, handleSubmit, formState: {errors},} = useForm<LoginForm>({mode: "onChange"});
 
const onSubmit = (data: LoginForm) => {
  console.log(data)
}
 return (
   <VStack>
     <form onSubmit={handleSubmit(onSubmit)}>
       <VStack>
         <FormLabel htmlFor="名前">First name</FormLabel>
         <Input id="name" type='text' {...register("name", {required: "名前は必須です", minLength: {value: 4, message: "4文字以上で入力してください"}})} />
         <Text color="red.500">{errors.name?.message as React.ReactNode}</Text>
         <Button mt={4} colorScheme="teal" type="submit">
           Submit
         </Button>
       </VStack>
     </form>
   </VStack>
 )
}
export default App;

コードが減ったのでスリムになりました。
バリデーションは名前が空の場合の条件と4文字以上の条件にしています。

image.png

image.png

4文字以上のバリデーションは文字を入力しているタイミングでチェックしてくれるようにしています。
これはuseFormのmode: "onChange"で指定することができます。

また、バリデートエラーが発生している際はボタンを押してもデータが送信されないようになっています。

image.png

おわりに

リファクタリングが捗りそうです

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?