React Hook FormでMaterial UIのCheckboxを制御でReact Hook Form v6でMaterial UIのCheckboxを制御する方法を紹介しました。
その後、React Hook Form v7がリリースされた。
React Hook Form v7でMaterial-UIを制御する方法が少し変わりましたので、Material UI v4のCheckboxを制御する方法をtypescriptでご紹介します。
今回ご紹介するCheckboxの制御仕様も前回と同じで以下の通りです。
そして完成したチェックボックスのフォームが以下のフォームです。
サンプルコード
import React, { useState } from "react";
import { useForm, FieldValues, Controller } from "react-hook-form";
import Button from "@material-ui/core/Button";
import Checkbox from "@material-ui/core/Checkbox";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import FormGroup from "@material-ui/core/FormGroup";
import FormHelperText from "@material-ui/core/FormHelperText";
import FormControl from "@material-ui/core/FormControl";
import FormLabel from "@material-ui/core/FormLabel";
export default function App() {
const [submitData, setSubmitData] = useState<string>("");
const defaultCheckedValues = ["B"];
// Options
const options = [
{
title: "A"
},
{
title: "B"
},
{
title: "C"
},
{
title: "D"
}
];
const {
formState: { errors },
control,
setValue,
getValues,
handleSubmit
} = useForm<FieldValues>({
criteriaMode: "all",
defaultValues: { checkbox: defaultCheckedValues.join(",") }
});
const handleFormOnSubmit = (data: any) => {
setSubmitData(data.checkbox);
};
const handleCheck = (
option: { title: string },
event: React.ChangeEvent<{}>
) => {
let values: string[] = getValues("checkbox")?.split(",") || [];
values = values.filter((v) => v); // 空要素削除
let newValues: string[] = [];
if ((event.target as HTMLInputElement).checked) {
newValues = [...(values ?? []), option.title];
} else {
newValues = values?.filter((value) => value !== option.title);
}
setValue("checkbox", newValues.join(","));
return newValues.join(",");
};
return (
<>
<form
method="POST"
onSubmit={handleSubmit(handleFormOnSubmit)}
encType="multipart/form-data"
>
<FormControl
required
error={errors?.hasOwnProperty("checkbox")}
component="fieldset"
fullWidth
>
<FormLabel component="legend">質問</FormLabel>
<FormHelperText>
{errors?.checkbox && errors?.checkbox.message}
</FormHelperText>
<FormGroup>
<Controller
name="checkbox"
control={control}
rules={{ required: "選択してください。" }}
defaultValue=""
render={({ field, fieldState }) => (
<>
{options.map((option, i) => (
<FormControlLabel
{...field}
key={i}
label={option.title}
onChange={(event) =>
field.onChange(handleCheck(option, event))
}
control={
<Checkbox
defaultChecked={defaultCheckedValues.includes(option.title)}
/>
}
/>
))}
</>
)}
/>
</FormGroup>
</FormControl>
<Button type="submit" variant="contained" color="primary">
送信
</Button>
</form>
<br />
送信内容
<br />
{submitData}
</>
);
}
要件を満たす制御の解説
制御する要件は以下の通りでした。
各要件に該当するコードの解説をします。
初期値に対応
初期値に対応するところではReact Hook Formは使わずにできます。
Material-UIのCheckboxにデフォルトチェックを入れておく項目を配列に入れておきます。
const defaultCheckedValues= ["B",];
次のコードのdefaultValues
でReact Hook Form用に初期値を定義します。defaultChecked.join(",")
で配列をカンマ区切りの文字にしています。
const {
formState: { errors },
control,
setValue,
getValues,
handleSubmit
} = useForm<FieldValues>({
criteriaMode: "all",
defaultValues: { checkbox: defaultCheckedValues.join(",") }
});
次にMaterial-UIのために初期値を定義します。Checkbox
のdefaultChecked
でdefaultCheckedValues
に値が入っているか確認をします。defaultCheckedValues
に値が入っていれば defaultChecked
はtrue
となります。
<Checkbox defaultChecked={defaultCheckedValues.includes(option.title)} />
これでデフォルトチェックを入れておくことができます。
チェックボックスの値の変更を制御
チェックボックスに変更があった場合、handleCheck
関数が実行されます。
handleCheck
関数内では
をしています。
const handleCheck = (
option: { title: string },
event: React.ChangeEvent<{}>
) => {
// チェック済みの値を取得
let values: string[] = getValues("checkbox")?.split(",") || [];
// 空要素削除
values = values.filter((v) => v);
// 変更を反映
let newValues: string[] = [];
if ((event.target as HTMLInputElement).checked) {
// 値を追加
newValues = [...(values ?? []), option.title];
} else {
// 値を除外
newValues = values?.filter((value) => value !== option.title);
}
setValue("checkbox", newValues.join(","));
return newValues.join(",");
};
チェック済みの値を取得部分ではgetValues()
でチェック済みの値を取得しています。
チェック済みの値がない場合はvaluesには空の配列が入ります。
空要素削除部分では、React Hook Form v7のgetValues()
で取得した値には空の値が入っていることがあるので、それを除外しています。
https://react-hook-form.com/api/useform/getvalues
Material UIのCheckboxグループを設置
Material UIのCheckbox
を複数設置する場合はReact Hook Form v7のController
のrender
内でチェックボックスグループ作ります。
React Hook Form v7のController
ごと複数生成しないように気をつけてください。
<FormGroup>
<Controller
name="checkbox"
control={control}
rules={{ required: "選択してください。" }}
defaultValue=""
render={({ field, fieldState }) => (
<>
{options.map((option, i) => (
<FormControlLabel
{...field}
key={i}
label={option.title}
onChange={(event) =>
field.onChange(handleCheck(option, event))
}
control={
<Checkbox
defaultChecked={defaultCheckedValues.includes(option.title)}
/>
}
/>
))}
</>
)}
/>
</FormGroup>
React Hook Form v7で制御しているMaterial-UIのCheckboxの値を取得して値を操作するにはFormControlLabel
にonChange
を記述する必要があります。
参考
https://react-hook-form.com/api/useform/
https://react-hook-form.com/ts#UseFormProps
下記に参考書をまとめておきます。
JavaScriptを基礎からしっかり学びたい方におすすめ!
JavaScriptを基礎から応用までガッツリ学びたい方におすすめ!
Reactの概念や仕組みを把握し、開発で使えるReactを学びたい方にオススメ!
コメント