LoginSignup
2
0

More than 1 year has passed since last update.

React-Hook-Formを使っていたらテキストフォームが入力できなくなった

Posted at

やりたいこと

下画面のようにラジオボタンの選択によってテキストフォームを出し分けたい
input-demo.png

前提知識

  • Reactの基本知識
  • typescriptの基本知識
  • chakra-uiの基本知識
  • react-hook-formの基本知識

発生した問題

Form.tsx
export function Form() {
  const { register, watch } = useForm();
  const [value, setValue] = useState("male");
  const watchText = watch("age", "");
  const elem = (
    <Box>
      <FormLabel>年齢</FormLabel>
      <Input
        {...register("age", {
          required: {
            value: true,
            message: "入力必須",
          },
        })}
      ></Input>
    </Box>
  );

  return (
    <Box margin="20px">
      <FormControl>
        <RadioGroup value={value} onChange={setValue}>
          <Box>
            <HStack>
              <Radio value="male">男性</Radio>
              <Fade in={value === "male"}>{elem}</Fade>
            </HStack>
          </Box>
          <Box>
            <HStack>
              <Radio value="female">女性</Radio>
              <Fade in={value === "female"}>{elem}</Fade>
            </HStack>
          </Box>
          <Box>
            <HStack>
              <Radio value="other">その他</Radio>
              <Fade in={value === "other"}>{elem}</Fade>
            </HStack>
          </Box>
        </RadioGroup>
        <Button colorScheme={"teal"}>送信</Button>
      </FormControl>
    </Box>
  );
}

elemでテキストフォームを定義し、ラジオボタンの選択によってelemを出現させようとしています。

しかしこれでは「男性」もしくは「女性」が選択されている場合 テキストフォームが入力不可になってしまいます。
そしてなぜか「その他」を選択された状態だと入力できます。この原因が分からずかなり苦戦してしまいました。

原因

コンポーネント内で使われていませんが

const watchText = watch("age", "");

このwatchTextのせいで入力不可となっていました。

watch()はreact-hook-formのメソッドで、registerによって登録したフィールド名(ここでは"age")を参照し
その入力内容を保持します。

しかし今回同じフィールド名で登録されているInput要素が3か所出現してしまっています。
これではwatchTextがどのInput要素を参照すればよいか分かりません。

これを制御するために「その他」のテキストフォームのみ入力可になっていたんだと思われます。

解決法

registerのフィールド名とInput要素は1対1にしなければなりません。
(Fadeタグのおかげで1対1になっていると思っていました:sweat_smile:)

<RadioGroup value={value} onChange={setValue}>
  <Box>
    <HStack>
      <Radio value="male">男性</Radio>
      <Fade in={value === "male"}>{value === "male" && elem}</Fade>
    </HStack>
  </Box>
  <Box>
    <HStack>
      <Radio value="female">女性</Radio>
      <Fade in={value === "female"}>{value === "female" && elem}</Fade>
    </HStack>
  </Box>
  <Box>
    <HStack>
      <Radio value="other">その他</Radio>
      <Fade in={value === "other"}>{value === "other" && elem}</Fade>
    </HStack>
  </Box>
</RadioGroup>

このようにすることで例えば「男性」が選択された場合、各Fadeタグ内の要素は順に elem, false, false となるためInput要素を1つにすることができます。

さいごに

単純な問題を難しく考えてしまっていましたが、同じような問題が発生した方の参考になればうれしいです!

2
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
2
0