Chakra UI Checkbox 少なくとも1つを選択するバリデーション設定の仕方

# はじめに
Checkboxのどれか１つでも選択することを必須とするバリデーションの設定に苦慮したため、そちらの解決方法を共有させていただきます。
 <br>
このようにCheckboxにrequired={true}を記述していました。これだと全ての項目にrequiredが付与されてしまい、全て選択するが必須になってしまいます。
```.Register.tsx

import { Box, Button, Card, CardBody, CardHeader, Checkbox, CheckboxGroup, FormLabel, Heading, Input, Radio, RadioGroup, Stack, Text, Textarea, useFormErrorStyles } from "@chakra-ui/react"
import { Controller, useForm } from "react-hook-form";

import { useSkills } from "../hooks/useSkills";
import { UserParams } from "../domain/users";

export const Register = () => {
  const { register, handleSubmit, control, formState: { errors } } = useForm<UserParams>();

  const { skillsData } = useSkills();


  return (
    <div>
      <Box display="flex" justifyContent="center" alignItems="center" height="100vh" bg="#e4e4e7">
      <Card pl={5} pr={5}>
        <CardHeader textAlign="center">
          <Heading size='lg'>新規名刺登録</Heading>
        </CardHeader>
        <Text ml={6} fontSize= "13px" as="span" color="#CC6666">* は必須項目です</Text>
        <Stack>
          <CardBody>
            <Box textAlign="center">
              <form onSubmit={handleSubmit((data) => {
                console.log("dataの中身", data);
              })}>

                 {/* ユーザーID */}
                <FormLabel fontWeight={"bold"}>ユーザーID <Text as="span" color="#CC6666">*</Text></FormLabel>
                  <Input type="text" placeholder="ユーザーIDを入力してください" {...register("user_id", { required: true})} />
                    <Box textAlign="left">{errors.user_id && <Text as="span" fontSize="14px" color="red">入力必須です</Text>}</Box>
                
                {/* 名前 */}
                <FormLabel fontWeight={"bold"} mt={2}>名前 <Text as="span" color="#CC6666">*</Text></FormLabel>
                  <Input type="text" placeholder="名前を入力してください" {...register("name", { required: true})} />
                    <Box textAlign="left">{errors.name && <Text as="span" fontSize= "14px" color="red">入力必須です</Text>}</Box>
                
                {/* 自己紹介 */}
                <FormLabel fontWeight={"bold"} mt={2}>自己紹介 <Text as="span" color="#CC6666">*</Text></FormLabel>
                  <Textarea placeholder="自己紹介文を入力してください。HTMLタグも使えます" {...register("description", { required: true})} />
                    <Box textAlign="left">{errors.description && <Text as="span" fontSize= "14px" color="red">入力必須です</Text>}</Box>
                
                {/* 好きな技術 */}
                <FormLabel fontWeight={"bold"} mt={2}>好きな技術 <Text as="span" color="#CC6666">*</Text></FormLabel>
                <Controller // controller使用しないと制御できない
                  name="skills" // どのﾌｨｰﾙﾄﾞを管理するか指定 ﾌｫｰﾑ送信時にここで指定した値がｵﾌﾞｼﾞｪｸﾄのｷｰとして扱われる
                  defaultValue={[]} // ﾃﾞﾌｫﾙﾄの値
                  control={control} // usFormから取得したcontrolを渡している。これによりｺﾝﾎﾟｰﾈﾝﾄがﾌｫｰﾑの状態管理に接続される
                  render={({ field }) => { // fieldという決まった名称のオブジェクト
                    return (
                      <CheckboxGroup value={field.value} onChange={(values) => field.onChange(values.map(Number))}> {/* Chakra uiのGroup Hook Formのﾃﾞﾌｫﾙﾄの値文字列から数値に変換が必要*/}

                        {skillsData.map((skill) => (
                          <Checkbox ml={1} mr={1} key={skill.id} value={skill.id} required={true}>{skill.name}</Checkbox>
                        ))}

                      </CheckboxGroup>
                    );
                  }}
                />

                 {/* GitHub ID */}
                <FormLabel mt={2}>GitHub ID</FormLabel>
                <Input placeholder="IDを入力してください" {...register("github_id")} />

                {/* Qiita ID */}
                <FormLabel mt={2}>Qiita ID</FormLabel>
                <Input placeholder="IDを入力してください" {...register("qiita_id")} />

                {/* X ID */}
                <FormLabel mt={2}>X ID</FormLabel>
                <Input placeholder="IDを入力してください" {...register("x_id")} />

                {/* 登録ボタン */}
                <Button mt={3} colorScheme='teal' type="submit">登録</Button>
              </form>
            </Box>
          </CardBody>
        </Stack>
      </Card>
      </Box>

    </div >
  )

}
```

# 解決方法
Controllerにrulesを設定する
```Register.tsx
import { Box, Button, Card, CardBody, CardHeader, Checkbox, CheckboxGroup, Flex, FormLabel, Heading, Input, Radio, RadioGroup, Stack, Text, Textarea, useFormErrorStyles } from "@chakra-ui/react"
import { Controller, useForm } from "react-hook-form";

import { useSkills } from "../hooks/useSkills";
import { UserParams } from "../domain/users";
import { getValueTransition } from "framer-motion";

export const Register = () => {
  const { register, handleSubmit, control, formState: { errors } } = useForm<UserParams>();

  const { skillsData } = useSkills();


  return (
    <div>
      <Box display="flex" justifyContent="center" alignItems="center" height="100vh" bg="#e4e4e7">
      <Card pl={5} pr={5}>
        <CardHeader textAlign="center">
          <Heading size='lg'>新規名刺登録</Heading>
        </CardHeader>
        <Flex><Text ml={6} as="span" color="#CC6666">*</Text><Text ml={1} fontSize="13px">は必須項目です</Text></Flex>
        <Stack>
          <CardBody>
            <Box textAlign="center">
              <form onSubmit={handleSubmit((data) => {
                console.log("dataの中身", data);
              })}>

                 {/* ユーザーID */}
                <FormLabel fontWeight={"bold"}>ユーザーID <Text as="span" color="#CC6666">*</Text></FormLabel>
                  <Input type="text" placeholder="ユーザーIDを入力してください" {...register("user_id", { required: true})} />
                    <Box textAlign="left">{errors.user_id && <Text as="span" fontSize="14px" color="red">入力必須です</Text>}</Box>
                
                {/* 名前 */}
                <FormLabel fontWeight={"bold"} mt={2}>名前 <Text as="span" color="#CC6666">*</Text></FormLabel>
                  <Input type="text" placeholder="名前を入力してください" {...register("name", { required: true})} />
                    <Box textAlign="left">{errors.name && <Text as="span" fontSize= "14px" color="red">入力必須です</Text>}</Box>
                
                {/* 自己紹介 */}
                <FormLabel fontWeight={"bold"} mt={2}>自己紹介 <Text as="span" color="#CC6666">*</Text></FormLabel>
                  <Textarea placeholder="自己紹介文を入力してください。HTMLタグも使えます" {...register("description", { required: true})} />
                    <Box textAlign="left">{errors.description && <Text as="span" fontSize= "14px" color="red">入力必須です</Text>}</Box>
                
                {/* 好きな技術 */}
                <FormLabel fontWeight={"bold"} mt={2}>好きな技術 <Text as="span" color="#CC6666">*</Text></FormLabel>
                <Controller // controller使用しないと制御できない
                  name="skills" // どのﾌｨｰﾙﾄﾞを管理するか指定 ﾌｫｰﾑ送信時にここで指定した値がｵﾌﾞｼﾞｪｸﾄのｷｰとして扱われる
                  defaultValue={[]} // ﾃﾞﾌｫﾙﾄの値
                  control={control} // usFormから取得したcontrolを渡している。これによりｺﾝﾎﾟｰﾈﾝﾄがﾌｫｰﾑの状態管理に接続される
                  rules={{
                    validate: (value) => {
                      if (!value || value.length === 0 ) { // valueがnullまたはundefinedの時に||の右を評価
                        return "少なくとも1つを選択してください";
                      }
                      return true;
                    }
                  }}
                  render={({ field }) => { // fieldという決まった名称のオブジェクト
                    return (
                      <CheckboxGroup value={field.value} onChange={(values) => field.onChange(values.map(Number))}> {/* Chakra uiのGroup Hook Formのﾃﾞﾌｫﾙﾄの値文字列から数値に変換が必要*/}

                        {skillsData.map((skill) => (
                          <Checkbox ml={1} mr={1} key={skill.id} value={skill.id} >{skill.name}</Checkbox>
                        ))}

                      </CheckboxGroup>
                    );
                  }}
                />
                {/* チェックボックスのエラーメッセージ */}
                <Box textAlign="left">{errors.skills && <Text as="span" fontSize="14px" color="red">{errors.skills.message}</Text>}</Box>

                 {/* GitHub ID */}
                <FormLabel mt={2}>GitHub ID</FormLabel>
                <Input placeholder="IDを入力してください" {...register("github_id")} />

                {/* Qiita ID */}
                <FormLabel mt={2}>Qiita ID</FormLabel>
                <Input placeholder="IDを入力してください" {...register("qiita_id")} />

                {/* X ID */}
                <FormLabel mt={2}>X ID</FormLabel>
                <Input placeholder="IDを入力してください" {...register("x_id")} />

                {/* 登録ボタン */}
                <Button mt={3} colorScheme='teal' type="submit">登録</Button>
              </form>
            </Box>
          </CardBody>
        </Stack>
      </Card>
      </Box>

    </div >
  )

}
```



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


# おわりに
react-hook-form便利ですね。

<br>

[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707255/8bfacf61-7d8d-6d27-cb07-98d1f8f27fcd.png"  width=100%>](https://projisou.jp)