はじめに
みなさんこんにちは torihaziです
現在、RailsとNext.jsでXクローン作成中なのですが
投稿の部分でめちゃめちゃ詰まりました。
投稿自体はできたのですがzodと組み合わせたvalidationがうまくいかなくて。
そこでReact-hook-formがサブスクライブしている情報を地道に追跡していったところ
なんとか解決できたのでそのやり方を。
といっても大したことないですけど。
今作ってるのはこんな感じです

結論
これを追記してください。あとはformいじりながらconsole.logで地道に追いかけるだけです。 ちなみにここでいうformはuseFormの返り値です。
useEffect(() => {
console.log("Form state:", {
isValid: form.formState.isValid,
isDirty: form.formState.isDirty,
errors: form.formState.errors,
touchedFields: form.formState.touchedFields,
dirtyFields: form.formState.dirtyFields,
});
}, [form.formState]);
終わりに
今回は本家のように画像かテキストは必ず必須というバリデーションを追加していたのですが
なぜか画像だけinputしても
submitのbuttonで設定していた
isDisabled={!(form.formState.isValid && form.formState.isDirty)}
がfalseにならなくて押せなくてかれこれ一日費やしてました。
export const imagesSchema = z.object({
images: z
.custom<FileList>()
.transform((file) => Array.from(file))
.refine((files) => files.length <= 4, {
message: "No more than 4 images",
})
.refine((files) => bytesToMB(calculateTotalSize(files)) <= 5, {
message: "Maximum file size: 5MB",
})
.refine((files) => validateImageExtension(files), {
message: "Only PNG (.png) and JPEG (.jpg, .jpeg)",
}),
});
export const tweetsPartialWithImagesSchema = tweetsSchema
.merge(imagesSchema)
.partial()
.refine((data) => data.content || (data.images && data.images.length > 0), {
message: "Either content or images is required",
path: ["content", "images"],
});
<= この最後のやつです。画像載っけたからOKになって通ると思ったのにダメだった。
結局この時はform.trigger()を使って事なきを得ました。
const onChange = async (e: ChangeEvent<HTMLInputElement>) => {
const filelists = e.target.files;
if (filelists) {
const urls = Array.from(filelists).map((file) =>
URL.createObjectURL(file)
);
form?.setValue("images", filelists);
const result = await form?.trigger();
if (result) {
setImageUrls(urls);
}
}
};
あとregisterから持ってきたonChageをカスタムしたら、setValueとかバリデーションも 手動でやんなきゃいけないっぽいんですかね。