[React+Tailwind] Form を TypeScript に書き直してみた | 心を無にして始める React
準備
書き直すベースはこちらの Form コンポーネントです。
JavaScript
ベースの Form.js です。
import { forwardRef } from 'react';
import {
Checkbox as FlowbiteCheckbox,
FileInput as FlowbiteFileInput,
Label as FlowbiteLabel,
Radio as FlowbiteRadio,
Select as FlowbiteSelect,
Textarea as FlowbiteTextarea,
TextInput as FlowbiteTextInput,
ToggleSwitch as FlowbiteToggleSwitch,
} from 'flowbite-react';
const Form = forwardRef((
{
children,
...otherProps
},
ref,
) => {
return (
<form
ref={ref}
{...otherProps}
>
{children}
</form>
);
});
const Checkbox = forwardRef((
{
...otherProps
},
ref,
) => {
return (
<FlowbiteCheckbox
ref={ref}
{...otherProps}
/>
);
});
const FileInput = forwardRef((
{
color = "gray",
helperText,
sizing = "md",
...otherProps
},
ref,
) => {
return (
<FlowbiteFileInput
color={color}
helperText={helperText}
ref={ref}
sizing={sizing}
{...otherProps}
/>
);
});
const Label = forwardRef((
{
children,
color = 'default',
disabled = false,
value,
...otherProps
},
ref,
) => {
return (
<FlowbiteLabel
color={color}
disabled={disabled}
ref={ref}
value={value}
{...otherProps}
>
{children}
</FlowbiteLabel>
);
});
const Radio = forwardRef((
{
...otherProps
},
ref,
) => {
return (
<FlowbiteRadio
ref={ref}
{...otherProps}
/>
);
});
const Select = forwardRef((
{
addon,
children,
color = 'gray',
helperText,
icon,
shadow = false,
sizing = 'md',
...otherProps
},
ref,
) => {
return (
<FlowbiteSelect
addon={addon}
color={color}
helperText={helperText}
icon={icon}
ref={ref}
shadow={shadow}
sizing={sizing}
{...otherProps}
>
{children}
</FlowbiteSelect>
);
});
const Textarea = forwardRef((
{
color = 'gray',
helperText,
shadow = false,
...otherProps
},
ref,
) => {
return (
<FlowbiteTextarea
color={color}
helperText={helperText}
ref={ref}
shadow={shadow}
{...otherProps}
/>
);
});
const TextInput = forwardRef((
{
addon,
color = 'gray',
helperText,
icon,
shadow = false,
sizing = 'md',
...otherProps
},
ref,
) => {
return (
<FlowbiteTextInput
addon={addon}
color={color}
helperText={helperText}
icon={icon}
ref={ref}
shadow={shadow}
sizing={sizing}
{...otherProps}
/>
);
});
const ToggleSwitch = forwardRef((
{
checked = false,
label,
onChange,
...otherProps
},
ref,
) => {
return (
<FlowbiteToggleSwitch
checked={checked}
label={label}
onChange={onChange}
ref={ref}
{...otherProps}
/>
);
});
export default Object.assign(Form, {
Checkbox,
FileInput,
Label,
Radio,
Select,
Textarea,
TextInput,
ToggleSwitch,
});
TypeScript
Form.tsx として編集します。
import { ComponentProps, forwardRef, LegacyRef, Ref, PropsWithChildren } from 'react';
import {
Checkbox as FlowbiteCheckbox,
CheckboxProps as FlowbiteCheckboxProps,
FileInput as FlowbiteFileInput,
FileInputProps as FlowbiteFileInputProps,
Label as FlowbiteLabel,
LabelProps as FlowbiteLabelProps,
Radio as FlowbiteRadio,
RadioProps as FlowbiteRadioProps,
Select as FlowbiteSelect,
SelectProps as FlowbiteSelectProps,
Textarea as FlowbiteTextarea,
TextareaProps as FlowbiteTextareaProps,
TextInput as FlowbiteTextInput,
TextInputProps as FlowbiteTextInputProps,
ToggleSwitch as FlowbiteToggleSwitch,
ToggleSwitchProps as FlowbiteToggleSwitchProps,
} from 'flowbite-react';
type FormProps = PropsWithChildren<ComponentProps<'form'>>;
const Form = forwardRef((
{
children,
...otherProps
}: FormProps,
ref: LegacyRef<HTMLFormElement>,
) => {
return (
<form
ref={ref}
{...otherProps}
>
{children}
</form>
);
});
type CheckboxProps = {} & FlowbiteCheckboxProps;
const Checkbox = forwardRef((
{
...otherProps
}: CheckboxProps,
ref: Ref<HTMLInputElement>,
) => {
return (
<FlowbiteCheckbox
ref={ref}
{...otherProps}
/>
);
});
type FileInputProps = {} & FlowbiteFileInputProps;
const FileInput = forwardRef((
{
color = "gray",
helperText,
sizing = "md",
...otherProps
}: FileInputProps,
ref: Ref<HTMLInputElement>,
) => {
return (
<FlowbiteFileInput
color={color}
helperText={helperText}
ref={ref}
sizing={sizing}
{...otherProps}
/>
);
});
type LabelProps = {} & FlowbiteLabelProps;
const Label = forwardRef((
{
children,
color = 'default',
disabled = false,
value,
...otherProps
}: LabelProps,
ref: LegacyRef<HTMLLabelElement>,
) => {
return (
<FlowbiteLabel
color={color}
disabled={disabled}
ref={ref}
value={value}
{...otherProps}
>
{children}
</FlowbiteLabel>
);
});
type RadioProps = {} & FlowbiteRadioProps;
const Radio = forwardRef((
{
...otherProps
}: RadioProps,
ref: Ref<HTMLInputElement>,
) => {
return (
<FlowbiteRadio
ref={ref}
{...otherProps}
/>
);
});
type SelectProps = {} & FlowbiteSelectProps;
const Select = forwardRef((
{
addon,
children,
color = 'gray',
helperText,
icon,
shadow = false,
sizing = 'md',
...otherProps
}: SelectProps,
ref: Ref<HTMLSelectElement>,
) => {
return (
<FlowbiteSelect
addon={addon}
color={color}
helperText={helperText}
icon={icon}
ref={ref}
shadow={shadow}
sizing={sizing}
{...otherProps}
>
{children}
</FlowbiteSelect>
);
});
type TextareaProps = {} & FlowbiteTextareaProps;
const Textarea = forwardRef((
{
color = 'gray',
helperText,
shadow = false,
...otherProps
}: TextareaProps,
ref: Ref<HTMLTextAreaElement>,
) => {
return (
<FlowbiteTextarea
color={color}
helperText={helperText}
ref={ref}
shadow={shadow}
{...otherProps}
/>
);
});
type TextInputProps = {} & FlowbiteTextInputProps;
const TextInput = forwardRef((
{
addon,
color = 'gray',
helperText,
icon,
shadow = false,
sizing = 'md',
...otherProps
}: TextInputProps,
ref: Ref<HTMLInputElement>,
) => {
return (
<FlowbiteTextInput
addon={addon}
color={color}
helperText={helperText}
icon={icon}
ref={ref}
shadow={shadow}
sizing={sizing}
{...otherProps}
/>
);
});
type ToggleSwitchProps = {} & FlowbiteToggleSwitchProps;
const ToggleSwitch = forwardRef((
{
checked = false,
label,
onChange,
...otherProps
}: ToggleSwitchProps,
ref: Ref<HTMLButtonElement>,
) => {
return (
<FlowbiteToggleSwitch
checked={checked}
label={label}
onChange={onChange}
ref={ref}
{...otherProps}
/>
);
});
export default Object.assign(Form, {
Checkbox,
FileInput,
Label,
Radio,
Select,
Textarea,
TextInput,
ToggleSwitch,
});
結果
変化はないので、前と同じ。
はい、できました。