Torihaji's Growth Diary

Little by little, no hurry.

React-Hook-Formのデバッグ方法で個人的にしっくりきたやつ

はじめに

みなさんこんにちは torihaziです

現在、RailsとNext.jsでXクローン作成中なのですが

投稿の部分でめちゃめちゃ詰まりました。

投稿自体はできたのですがzodと組み合わせたvalidationがうまくいかなくて。

そこでReact-hook-formがサブスクライブしている情報を地道に追跡していったところ

なんとか解決できたのでそのやり方を。

といっても大したことないですけど。

今作ってるのはこんな感じです

スクリーンショット 2024-10-19 14.43.11.png

結論

これを追記してください。あとは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とかバリデーションも 手動でやんなきゃいけないっぽいんですかね。