話としてはこれの続きです
https://qiita.com/stopod/items/42ac91a67037e849e97f
目標
- もっと簡単にFormを作成したい
実際のソースコード
やったこと
だいたいはこのPRに込められてます
課題点はここです
<ConfromField
label="性"
required
id={fields.lastName.id}
errorId={fields.lastName.errorId}
errorText={fields.lastName.errors}
invalid={!!fields.lastName.errors?.length}
>
<Input
placeholder="性"
variant="outline"
{...getInputProps(fields.lastName, { type: "text" })}
/>
</ConfromField>
これをこうしました
<FormFieldText
label="姓"
inputProps={{
...getInputTypeTextProps(fields.lastName),
}}
/>
Conformに用意されているヘルパーからだとerrorId, errorText等が取得できず、個別で受け取る必要がありました
また、FieldComponentとInputComponentでそれぞれ必要なものがあるのでまとめて、ヘルパーからまとめて渡すことができませんでした
なので以下のようにしました
- FiledとInputをまとめたform-filed-textというcomponentを作成
- ヘルパー関数をラップしたものを作成
それがこれです
import { Input, InputProps } from "@chakra-ui/react";
import { ConfromField, ConfromFieldProps } from "../ui/field";
import { FieldMetadata, getInputProps } from "@conform-to/react";
import { ReactNode } from "react";
type FormFiledTextProps = ConfromFieldProps & {
inputProps?: InputProps & {
errorId?: string;
errorText?: ReactNode;
invalid?: boolean;
};
};
export const FormFieldText = (props: FormFiledTextProps) => {
const { inputProps, ...rest } = props;
const { id, errorId, errorText, invalid, required, ...inputPropsRest } =
inputProps || {};
return (
<ConfromField
id={id}
errorId={errorId}
errorText={errorText}
invalid={invalid}
required={required}
{...rest}
>
<Input id={id} {...inputPropsRest} />
</ConfromField>
);
};
export const getInputTypeTextProps = (metadata: FieldMetadata) => {
const errorId = metadata.errorId;
const errorText = metadata.errors;
const invalid = !metadata.valid;
return {
errorId,
errorText,
invalid,
...getInputProps(metadata, { type: "text" }),
};
};
export const getInputTypeDateProps = (metadata: FieldMetadata) => {
const errorId = metadata.errorId;
const errorText = metadata.errors;
const invalid = !metadata.valid;
return {
errorId,
errorText,
invalid,
...getInputProps(metadata, { type: "date" }),
};
};
ヘルパー関数としてこれが適切なカスタマイズ方法かがわかりませんが、getInputTypeTextPropsを作成してerrorId, errorText, invalidを付与するようにしました
これをComponent側で分解してFiledとInputにそれぞれ適切に渡します
そうすることで呼び出し側では(基本的には)ヘルパー関数だけで入力フォームが完成します
似たような感じでselect componentも分離してヘルパー関数をラップした関数を作りました
https://github.com/stopod/rr-chakra-conform-sample/commit/e34dcee19c1f0239b85dd0b63bd56764f2d85305#diff-a573f4e9daaa115b6c047848fa5a19015971f432b7f88446c12c60e42300b5f2
終わりに
ついでにReactRouter v7がリリースされたのでv7.0.1にしました
ヘルパー関数の扱いがわからないのと(ググるとこんな適当にカスタマイズしてるのではなくて、ちゃんとなんかもにょもにょしている人がいた)、FieldとInputをまとめたcomponentにおけるpropsのいい感じの扱いがわからない