はじめに
みなさんこんにちは 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とかバリデーションも 手動でやんなきゃいけないっぽいんですかね。