shadcn-ui / ui

Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.
https://ui.shadcn.com
MIT License
74.72k stars 4.65k forks source link

[Bug]: TypeScript Error: Incompatible `value` type in `InputProps` #2997

Open OmarAfet opened 8 months ago

OmarAfet commented 8 months ago

Describe the bug

I'm encountering a TypeScript error in my NextJS app when trying to use an Input component for file uploads. The error message is as follows:

Type '{ multiple: true; type: "file"; accept: string; onChange: (...event: any[]) => void; onBlur: Noop; value: File[]; disabled?: boolean | undefined; name: "images"; ref: RefCallBack; }' is not assignable to type 'InputProps'.
  Types of property 'value' are incompatible.
    Type 'File[]' is not assignable to type 'string | number | readonly string[] | undefined'.
      Type 'File[]' is not assignable to type 'readonly string[]'.
        Type 'File' is not assignable to type 'string'.ts(2322)

The error occurs in the following code snippet:

<FormField
    control={form.control}
    name="images"
    render={({ field }) => (
        <FormItem>
            <FormLabel>
                images <span className="text-muted-foreground">(You can upload up to 5 images)</span>
            </FormLabel>
            <FormControl>
                <Input {...field} multiple type="file" accept="image/jpeg, image/png" />
            </FormControl>
            <FormMessage />
        </FormItem>
    )}
/>

The Input component is being used with the react-hook-form library and the zod schema validation library. The relevant part of the schema is:

images: z.array(
    z
        .instanceof(File)
        .refine((file) => file.size <= MAX_UPLOAD_SIZE, "Image size must be less than 1MB.")
        .refine((file) => ACCEPTED_FILE_TYPES.includes(file.type), "Invalid file type. Only JPEG and PNG are allowed.")
),

The Input component's value prop is expected to be a string | number | readonly string[] | undefined, but it's receiving a File[] due to the images field in the form.

Any help resolving this issue would be greatly appreciated.

Affected component/components

Input

How to reproduce

  1. Create a NextJS app.
  2. Install these packages:
    npm i zod react-hook-form && npx shadcn-ui@latest add form && npx shadcn-ui@latest add input
  3. In app/page.tsx add this code:
    
    'use client';

import { Input } from '@/components/ui/input'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from '@/components/ui/form';

const MAX_UPLOAD_SIZE = 1024 1024 1; // 1MB const ACCEPTED_FILE_TYPES = ['image/jpeg', 'image/png'];

const schema = z.object({ images: z.array( z .instanceof(File) .refine( (file) => file.size <= MAX_UPLOAD_SIZE, 'Image size must be less than 1MB.' ) .refine( (file) => ACCEPTED_FILE_TYPES.includes(file.type), 'Invalid file type. Only JPEG and PNG are allowed.' ) ), });

export default function Home() { const form = useForm<z.infer>({ resolver: zodResolver(schema), defaultValues: { images: [new File([], '')], }, });

function onSubmit(values: z.infer) { console.log(values); }

return (

( images )} />

); }


### Codesandbox/StackBlitz link

https://stackblitz.com/edit/shadcn-ui-issue-2997?file=app%2Fpage.tsx

### Logs

```bat
Unhandled Runtime Error
InvalidStateError: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.

Call Stack
initInput
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (3581:0)
setInitialProperties
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (33346:0)
finalizeInitialChildren
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (35368:0)
completeWork
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (19725:0)
completeUnitOfWork
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (25843:0)
performUnitOfWork
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (25648:0)
workLoopSync
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (25353:0)
renderRootSync
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (25308:0)
recoverFromConcurrentError
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (24525:0)
performConcurrentWorkOnRoot
(app-pages-browser)/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (24470:0)
workLoop
(app-pages-browser)/node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js (256:0)
flushWork
(app-pages-browser)/node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js (225:0)
MessagePort.performWorkUntilDeadline
(app-pages-browser)/node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js (534:0)
Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.
    at initInput (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:3581:22)
    at setInitialProperties (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:33346:9)
    at finalizeInitialChildren (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:35368:3)
    at completeWork (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19725:17)
    at completeUnitOfWork (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:25843:14)
    at performUnitOfWork (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:25648:5)
    at workLoopSync (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:25353:5)
    at renderRootSync (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:25308:7)
    at recoverFromConcurrentError (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24525:20)
    at performConcurrentWorkOnRoot (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24470:26)
    at workLoop (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:256:34)
    at flushWork (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:225:14)
    at MessagePort.performWorkUntilDeadline (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:534:21)
app-index.js:35 The above error occurred in the <NotFoundErrorBoundary> component:

    at NotFoundErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:76:9)
    at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11)
    at DevRootNotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/dev-root-not-found-boundary.js:33:11)
    at ReactDevOverlay (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/internal/ReactDevOverlay.js:84:9)
    at HotReload (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:307:11)
    at Router (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:182:11)
    at ErrorBoundaryHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:114:9)
    at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:161:11)
    at AppRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:538:13)
    at ServerRoot (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:129:11)
    at RSCComponent
    at Root (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:145:11)
    at ReactDevOverlay (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/internal/ReactDevOverlay.js:84:9)

React will try to recreate this component tree from scratch using the error boundary you provided, ReactDevOverlay.

System Info

Edition Windows 10 Pro
Version 22H2
Installed on    ‎2022-‎01-‎18
OS build    19045.4123
Experience  Windows Feature Experience Pack 1000.19054.1000.0

Google Chrome Version 122.0.6261.112 (Official Build) (64-bit)

Before submitting

Nilesh-Meena commented 8 months ago

HTML input elements, including file input, <input type=" file">, accept a value prop. These value props represent a selected file. For security purposes in the browser, setting the value is not allowed. Therefore, we cannot directly set value props to a 'File 'object or array. Here, react-hook-form manages the form state and file uploads. And also handles the value input field itself. It's expecting undefined initially, allowing the user to select files via the browser file picker. By setting value={undefined} we can resolve this. This will indicate to react-hook-form that the field is initially empty. And may avoid the error you are encountering.

defaultValues: {
  images: [undefined], // Set initial value to undefined instead of new File([], '')
},
<Input
  {...field}
  multiple
  type="file"
  accept="image/jpeg, image/png"
  value={undefined} // Set value to undefined for file input field
/>

Source -> https://stackoverflow.com/questions/72557334/react-hook-form-and-setvalue-of-file-input

OmarAfet commented 8 months ago

Thanks @Nilesh-Meena , this fixes the TypeScript error. but now when I upload an image(s), a validation error occurs saying Expected array, received string

Nilesh-Meena commented 8 months ago

We can initialize image with an empty array [] rather than a single element in an array with undefined. I hope this works.

OmarAfet commented 8 months ago

We can initialize image with an empty array [] rather than a single element in an array with undefined. I hope this works.

It doesn't work. The problem isn't with the initial value; it's about Zod schema validation.

export const schema = z.object({
  images: z.array(
      z
          .instanceof(File)
          .refine((file) => file.size <= MAX_UPLOAD_SIZE, "Image size must be less than 1MB.")
          .refine((file) => ACCEPTED_FILE_TYPES.includes(file.type), "Invalid file type. Only JPEG and 
  PNG are allowed.")
  ),
});
Nilesh-Meena commented 8 months ago

I think the issue is input component is passing a string value to the image field. which is expected to be an array according to Zod schema. I have updated both the Zod schema and the Input props to resolve this. Edit the code however you like.

"use client";

import { Input } from "@/components/ui/input";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { string, z } from "zod";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import { Button } from "@/components/ui/button";

const MAX_UPLOAD_SIZE = 1024 * 1024 * 1; // 1MB
const ACCEPTED_FILE_TYPES = ["image/jpeg", "image/png"];

const schema = z.object({
  images: z
    .array(
      z
        .any()
        .refine(
          (file) => file?.size <= MAX_UPLOAD_SIZE,
          `Max image size is 1 MB.`
        )
        .refine(
          (file) => ACCEPTED_FILE_TYPES.includes(file?.type),
          "Only.jpeg, .png formats are supported."
        )
    )
    .default([]), // Default value for array field
});

export default function Home() {
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
  });
  const [validationErrors, setValidationErrors] = useState<string[]>([]);

  async function onSubmit(formData: z.infer<typeof schema>) {
    try {
      // Check for oversized files
      const oversizedFiles = formData.images.filter(
        (file) => file.size > MAX_UPLOAD_SIZE
      );
      if (oversizedFiles.length > 0) {
        setValidationErrors([`Max image size is 1 MB.`]);
        return; 
      }

      // If no oversized files
      await schema.parseAsync(formData);
      console.log("Form data submitted:", formData);
    } catch (error) {
      if (error instanceof Error) {
        console.error("Validation failed:", error.message);
      } else {
        console.error("An unexpected error occurred:", error);
      }
    }
  }

  return (
    <main>
      <Form {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)}>
          <FormField
            control={form.control}
            name="images"
            render={({ field }) => (
              <FormItem>
                <FormLabel>images</FormLabel>
                <FormControl>
                  <Input
                    {...field}
                    multiple
                    type="file"
                    accept="image/jpeg, image/png"
                    value={undefined}
                    onChange={(e) => {
                      const files = e.target.files;
                      if (files) {
                        const fileList = Array.from(files);
                        const oversizedFiles = fileList.filter(
                          (file) => file.size > MAX_UPLOAD_SIZE
                        );
                        if (oversizedFiles.length > 0) {
                          setValidationErrors([`Max image size is 1MB.`]);
                        } else {
                          setValidationErrors([]);
                          field.onChange(fileList);
                        }
                      }
                    }}
                  />
                </FormControl>
                <FormMessage>{validationErrors.join(", ")}</FormMessage>
              </FormItem>
            )}
          />
          <Button type="submit">Submit</Button>
        </form>
      </Form>
    </main>
  );
}

When No file is selected: image array is empty image

when a single file is selected: image array shows 1 file image

when multiple file is selected: image array shows multiple files image

When file size exceeds:

Currently, we are not storing previously added images to the array. if you want this functionality you can do this.

  1. Maintain a single array for storing selected images.
  2. Calculate the total size of the selected images when adding a new image and ensure it doesn't exceed 1MB.
  3. Display an error message if the total size exceeds the limit.
OmarAfet commented 8 months ago

Thank you for your code. I've made some changes to improve type safety and added default values for the form fields. But, I'm facing an issue where the custom error messages from the Zod schema aren't displaying correctly. Instead, I'm getting undefined

I noticed that you've created a state for error messages, but I believe this isn't the ideal solution. Zod should handle that, and we need to fix it.

Check out the code here with the new changes I've made. Try to submit without files and with files more than 1MB. It will show undefined. I'm not sure why this is happening, but I suspect it might be due to value={undefined}.

EDIT: After removing the z.array(...) part, the undefined error was replaced with actual errors.

image

Nilesh-Meena commented 8 months ago

you are right, Zod should handle the validation. I have updated the code. Previously I was experimenting with the code and trying to find where the error Expected array, received string came from. And then I forgot to remove the states for the error message.

This updated code checks both file size and file type within a single .refine() call. if both checks pass, Zod considers the validation field to have passed, and no error message is returned. And we update the formData, as you can see in the attached images.

'use client';

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form';
import * as z from 'zod';

const MAX_FILE_SIZE = 1024 * 1024 * 1;
const ACCEPTED_IMAGE_EXTENSIONS = ['jpeg', 'jpg', 'png'];

const formSchema = z.object({
  adImage: z.array(z.any()).refine(
    (files) => {
      // Check if any file exceeds the maximum size
      const maxSizeExceeded = files.some(
        (file) => file?.file?.size > MAX_FILE_SIZE
      );
      if (maxSizeExceeded) {
        return false;
      }

      // Check if all files have an accepted file extension
      const invalidFileExtension = files.some((file) => {
        const fileNameParts = file?.file?.name.split('.');
        const fileExtension = fileNameParts[fileNameParts.length - 1];
        return !ACCEPTED_IMAGE_EXTENSIONS.includes(fileExtension.toLowerCase());
      });
      return !invalidFileExtension;
    },
    {
      message: 'File exceeds the maximum size, or unsupported file extension.',
    }
  ),
});

export default function MyForm() {
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      adImage: undefined,
    },
  });

  const onSubmit = (formData: z.infer<typeof formSchema>) => {
    console.log('button clicked');
    console.log('Form data:', formData.adImage);
  };

  const handleFileSelection = (e: any, field: any) => {
    const files = e.target.files;
    if (files && files.length > 0) {
      const fileList = Array.from(files); // Convert FileList to array
      const validatedFiles = fileList.map((file) => ({
        file,
      })); // Validate each file
      field.onChange(validatedFiles); // Update form field value
    }
  };

  return (
    <main>
      <Form {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)}>
          <FormField
            control={form.control}
            name="adImage"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Images</FormLabel>
                <FormControl>
                  <Input
                    {...field}
                    multiple
                    type="file"
                    accept="image/jpeg, image/png"
                    value={undefined}
                    onChange={(e) => handleFileSelection(e, field)}
                  />
                </FormControl>
                {/* Display form error message */}
                {/* <FormMessage>
                  {formState.errors.adImage?.message || ''}
                </FormMessage> */}
              </FormItem>
            )}
          />
          <FormMessage>{form.formState.errors.adImage?.message}</FormMessage>
          <Button type="submit">Submit</Button>
        </form>
      </Form>
    </main>
  );
}

When No image is selected: image

When Invalid file type is selected: image

when the File exceeds the limit: image

When Everything checks out we should be able to add the image: image

image

OmarAfet commented 8 months ago

Thanks @Nilesh-Meena for your code.

The problem with the error message undefined was with the z.array() function. Therefore, adding .refine() after z.array() instead of within it solves the issue.

I don't know what the issue is related to... Shadcn, react-hook-form, or zod, so I'll keep it open for @shadcn to view it before closing it.

For anyone wanting a Shadcn input file that accepts multiple files with Zod validation and react-hook-form, here's a simple form:

"use client";

import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";

const MAX_UPLOAD_SIZE = 1024 * 1024 * 1; // 1MB
const ACCEPTED_FILE_TYPES = ["image/jpeg", "image/png"];

const schema = z.object({
  images: z
    .array(z.instanceof(File))
    .min(1, "You must upload at least 1 image.")
    .max(3, "You can upload a maximum of 3 images.")
    .refine((files) => files.every((file) => file.size <= MAX_UPLOAD_SIZE && ACCEPTED_FILE_TYPES.includes(file.type)), "All images must be less than 1MB and of type JPEG or PNG."),
});

export default function Home() {
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: {
      images: [new File([], "")],
    },
  });

  function onSubmit(values: z.infer<typeof schema>) {
    console.log(values);
  }

  return (
    <main>
      <Form {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
          <FormField
            control={form.control}
            name="images"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Images</FormLabel>
                <FormControl>
                  <Input
                    {...field}
                    multiple
                    type="file"
                    accept="image/jpeg, image/png"
                    value={undefined}
                    onChange={(e) => {
                      const files = e.target.files;
                      if (files) {
                        field.onChange(Array.from(files));
                      }
                    }}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          <Button className="w-full" type="submit">
            Submit
          </Button>
        </form>
      </Form>
    </main>
  );
}
OmarAfet commented 8 months ago

The issue still seems to be present; I can't send a form with that file input.

Jenrikk commented 7 months ago

the solution of setting undefined in defaultvalues and also in the input value={undefined} works fine in fields where user can write. But it doesn't work in readOnly input. This input is modified automatically in a useEffect using form.setValue("pricePerUnit", result). it sets the value only when I remove the undefined values in defaultvalues and value={undefined}

fxmb commented 1 month ago

still an issue right?

OmarAfet commented 1 month ago

The core problem lies in how the Input component handles the value prop when dealing with file inputs. When using an <input type="file">, the value attribute is read-only in browsers due to security reasons; it can only be programmatically set to an empty string ('' or undefined), not to an array of File objects or any other value.

In this case, the react-hook-form's field object includes a value property, which when spread into the Input component (<Input {...field} />), causes the value prop to be set to a File[]. This leads to the TypeScript error you're seeing, as well as runtime errors when the browser tries to handle the value of the file input.

So, instead of spreading the entire field object into the Input component, extract only the necessary properties and omit value.

// The `field` object includes the `value` property, which should be omitted
<FormField
  control={form.control}
  name="images"
  render={({ field }) => (
    <FormItem>
      <FormLabel>Images</FormLabel>
      <FormControl>
        <Input
          name={field.name}
          ref={field.ref}
          onBlur={field.onBlur}
          onChange={(e) => {
            const files = e.target.files;
            if (files) {
              // Convert FileList to an array and update form state
              field.onChange(Array.from(files));
            }
          }}
          multiple
          type="file"
          accept="image/jpeg, image/png"
        />
      </FormControl>
      <FormMessage />
    </FormItem>
  )}
/>

But there's one more thing to consider: you can't pass instances of the File class directly to a Server Action because Next.js only supports serializable data types like plain objects, arrays, strings, numbers, and a few built-in types. They do not support class instances like File.

To work around this limitation, you can use a FormData object to send the files to the server. Here's an example of how you can do this:

async function onSubmit(values: z.infer<typeof schema>) {
  const formData = new FormData();

  values.images.forEach((file) => {
    formData.append("images", file);
  });

  await serverAction(formData); // Send the form data to the server
}

Also, don't forget to add the encType="multipart/form-data" attribute to the <form> tag to ensure that file data is correctly encoded and transmitted to the server.

Full Code ```tsx "use client"; import { serverAction } from "@/actions/test"; import { Button } from "@/components/ui/button"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { z } from "zod"; const MAX_UPLOAD_SIZE = 1024 * 1024 * 1; // 1MB const ACCEPTED_FILE_TYPES = ["image/jpeg", "image/png"]; const schema = z.object({ images: z .array(z.instanceof(File)) .nonempty("You must upload at least 1 image.") .max(3, "You can upload a maximum of 3 images.") .refine( (files) => files.every( (file) => file.size <= MAX_UPLOAD_SIZE && ACCEPTED_FILE_TYPES.includes(file.type) ), "All images must be less than 1MB and of type JPEG or PNG." ), }); export default function Page() { const form = useForm>({ resolver: zodResolver(schema), defaultValues: { images: [], // Initialize with an empty array }, }); async function onSubmit(values: z.infer) { console.log(values); const formData = new FormData(); values.images.forEach((file) => { formData.append("images", file); }); await serverAction(formData); } return (
( Images { const files = e.target.files; if (files) { // Convert FileList to an array and update form state field.onChange(Array.from(files)); } }} multiple type="file" accept="image/jpeg, image/png" /> )} />
); } ```

References:

React Hook Form MDN Web Docs on Next.js Server Actions

hedaetul commented 1 month ago

Thank you for your code. I've made some changes to improve type safety and added default values for the form fields. But, I'm facing an issue where the custom error messages from the Zod schema aren't displaying correctly. Instead, I'm getting undefined

I noticed that you've created a state for error messages, but I believe this isn't the ideal solution. Zod should handle that, and we need to fix it.

Check out the code here with the new changes I've made. Try to submit without files and with files more than 1MB. It will show undefined. I'm not sure why this is happening, but I suspect it might be due to value={undefined}.

EDIT: After removing the z.array(...) part, the undefined error was replaced with actual errors.

image

i have a question: What will be the data type of the image input if I have to use it in another component? Will it be an array or a File?e?