目的
基本的な useFormと material UIの利用がまとっまっているので、 都度確認しやすくする
なんで useForm利用するのか?
・シンプルにformの値が管理しやすい ・material ui などのUIライブラリや Typescriptなどの型利用が一般的になったので、 独自開発するより良い
この記事でわかること
- Material UI datepickers, radio buttons, dropdowns, and slidersと useFormの統合が分かる
useForm基本
- useFormはいろんなメソッドがある
const { register, handleSubmit, reset, control, setValue } = useForm();
- MUI などを利用しない場合は下記のようなシンプルな利用
<input type="text" ref={register} name="firstName" />
- TextInputの場合
import { Controller } from "react-hook-form"; import TextField from "@mui/material/TextField"; import { FormInputProps } from "./FormInputProps"; export const FormInputText = ({ name, control, label }: FormInputProps) => { return ( <Controller name={name} control={control} render={({ field: { onChange, value }, fieldState: { error }, formState, }) => ( <TextField helperText={error ? error.message : null} size="small" error={!!error} onChange={onChange} value={value} fullWidth label={label} variant="outlined" /> )} /> ); };
- ラジオボタンの場合
// src/form-component/FormInputRadio.tsx import { FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, } from "@mui/material"; import { Controller } from "react-hook-form"; import { FormInputProps } from "./FormInputProps"; const options = [ { label: "Radio Option 1", value: "1", }, { label: "Radio Option 2", value: "2", }, ]; export const FormInputRadio: React.FC<FormInputProps> = ({ name, control, label, }) => { const generateRadioOptions = () => { return options.map((singleOption) => ( <FormControlLabel value={singleOption.value} label={singleOption.label} control={<Radio />} /> )); }; return ( <FormControl component="fieldset"> <FormLabel component="legend">{label}</FormLabel> <Controller name={name} control={control} render={({ field: { onChange, value }, fieldState: { error }, formState, }) => ( <RadioGroup value={value} onChange={onChange}> {generateRadioOptions()} </RadioGroup> )} /> </FormControl>
- dropwodn
// src/form-component/FormInputDropdown.tsx import { FormControl, InputLabel, MenuItem, Select } from "@mui/material"; import { Controller } from "react-hook-form"; import { FormInputProps } from "./FormInputProps"; const options = [ { label: "Dropdown Option 1", value: "1", }, { label: "Dropdown Option 2", value: "2", }, ]; export const FormInputDropdown: React.FC<FormInputProps> = ({ name, control, label, }) => { const generateSingleOptions = () => { return options.map((option: any) => { return ( <MenuItem key={option.value} value={option.value}> {option.label} </MenuItem> ); }); }; return ( <FormControl size={"small"}> <InputLabel>{label}</InputLabel> <Controller render={({ field: { onChange, value } }) => ( <Select onChange={onChange} value={value}> {generateSingleOptions()} </Select> )} control={control} name={name} /> </FormControl> ); };
- checknbox
// src/form-component/FormInputMultiCheckbox.tsx import React, { useEffect, useState } from "react"; import { Checkbox, FormControl, FormControlLabel, FormLabel, } from "@mui/material"; import { Controller } from "react-hook-form"; import { FormInputProps } from "./FormInputProps"; const options = [ { label: "Checkbox Option 1", value: "1", }, { label: "Checkbox Option 2", value: "2", }, ]; export const FormInputMultiCheckbox: React.FC<FormInputProps> = ({ name, control, setValue, label, }) => { const [selectedItems, setSelectedItems] = useState<any>([]); // we are handling the selection manually here const handleSelect = (value: any) => { const isPresent = selectedItems.indexOf(value); if (isPresent !== -1) { const remaining = selectedItems.filter((item: any) => item !== value); setSelectedItems(remaining); } else { setSelectedItems((prevItems: any) => [...prevItems, value]); } }; // we are setting form value manually here useEffect(() => { setValue(name, selectedItems); }, [name, selectedItems, setValue]); return ( <FormControl size={"small"} variant={"outlined"}> <FormLabel component="legend">{label}</FormLabel> <div> {options.map((option: any) => { return ( <FormControlLabel control={ <Controller name={name} render={({ field }) => { return ( <Checkbox checked={selectedItems.includes(option.value)} onChange={() => handleSelect(option.value)} /> ); }} control={control} /> } label={option.label} key={option.value} /> ); })} </div> </FormControl> ); };
- date with datepicker
/ src/form-component/FormInputDate.tsx import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { Controller } from "react-hook-form"; import { FormInputProps } from "./FormInputProps"; export const FormInputDate = ({ name, control, label }: FormInputProps) => { return ( <LocalizationProvider dateAdapter={AdapterDateFns}> <Controller name={name} control={control} render={({ field: { onChange, value } }) => ( <DatePicker value={value} onChange={onChange} /> )} /> </LocalizationProvider> ); };