-
Notifications
You must be signed in to change notification settings - Fork 5.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
React error "uncontrolled input" in forms (demo repo provided) #410
Comments
same problem |
So, since const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
+ username: "",
},
}) From the docs:
(Edit: I've update the example in the docs) |
Thank you very much 🙂 |
I have a number input, so I can't set the default value to an empty string. |
@Wouter8 you can set a number as default value. |
I think an |
I can't manually provide the value since it is being controlled (implementation of I can't apply an empty string in the const formSchema = z.object({
number: z.number().int().min(1),
});
export default function Component() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
number: "",
},
});
Setting This does not solve the issue since |
Hm... it seems like you would need to, either:
|
I don't really understand this behavior. I think it's counter-intuitive to have a default value as a must in this case. I have a form and a select with multiple choices inside and I want to show the placeholder by default and not a selected value. Let's say the selector is |
The question is how do I check that my field is an empty string? |
And required_error of |
I used it to trigger
|
this seems to resolve this issue, hook-form and zod still see the field.value, which is undefined, but the component recieves an empty string instead of undefined. |
What are your default values? |
for hook-form, undefined, but the input is tricked into it being an empty string |
Thanks for this @tarikyildizci, helps get around the default values tripping zod for required inputs. This must be a very common problem, it's the most basic implementation of a form, this should have more attention imo. |
Thank goodness I ran across this thread, so I'm not totally crazy. It's kinda blowing my mind that very straightforward and simple use cases like this aren't working out of the box.
I'm seeing an issue with this solution when I use a simple validation like
It's also unclear to me how this should work in the cases of other input types, like dates, or something like a text input where I want to coerce the value to a date or number (i.e. DOB). Surely there's a straightforward solution to all this somewhere? |
Can I use the uncontrolled component with react-hook-form? If so, we can implement it: const formSchema = z.object({
totalArea: z.union([z.number().int().positive().min(1), z.nan()]).optional(),
})
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
// no default value for totalArea
},
})
<FormField
control={form.control}
name="totalArea"
render={({ field }) => (
<FormItem>
<FormLabel>총 재배면적</FormLabel>
<FormControl>
<Input type="number"
// using uncontrolled component with react-hook-form
{...form.register("totalArea", { setValueAs: v => v === "" ? undefined : parseInt(v, 10) })}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/> It works fine to me. But I'm still not sure if I'm missing some features from |
This for me work! |
You can use zod coerce method and set the default value of the number to empty string. Downsides
|
I have same issue and I wonder any solution for default value that is not empty string & arbitrary value in optional number field? |
Also interested in this, trying to have number validation in a form. I simply cannot get it to work and am falling back to very hacky solutions validating on later on before storing the data but would be nice to have this working out of the box. Tagging this; will dig a little more and see if I come up with something. |
I've implemented numbers in Zod using the following: function requiredNumberTransform(num: number | "", ctx: z.RefinementCtx) {
if (num === "") {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Enter a number",
fatal: true,
});
return z.NEVER;
}
return num;
}
const OptionalNumber = z.number().or(z.literal(""));
const RequiredNumber = OptionalNumber.transform(requiredNumberTransform); This works with |
I think you can use the form.resetField("username") and that will still consider it untouched ? |
So for a controlled input, there is no way to only validate values that the user has entered itself?
|
Optional inputs in controlled forms are problematic, because (1) Specifying default values for them in the `useForm` hook leads to unnecessary payload sent from the form, so rather keep them as `undefined`, which means the corresponding parameter is not included in the payload. (2) Leaving them without default values causes a React warning about a component transferring from uncontrolled to controlled state. Alleviate these problems with a component specifically used for optional inputs [1]. [1]: shadcn-ui/ui#410 (comment)
Optional inputs in controlled forms are problematic, because (1) Specifying default values for them in the `useForm` hook leads to unnecessary payload sent from the form, so rather keep them as `undefined`, which means the corresponding parameter is not included in the payload. (2) Leaving them without default values causes a React warning about a component transferring from uncontrolled to controlled state. Alleviate these problems with a component specifically used for optional inputs [1]. [1]: shadcn-ui/ui#410 (comment)
Optional inputs in controlled forms are problematic, because (1) Specifying default values for them in the `useForm` hook leads to unnecessary payload sent from the form, so rather keep them as `undefined`, which means the corresponding parameter is not included in the payload. (2) Leaving them without default values causes a React warning about a component transferring from uncontrolled to controlled state. Alleviate these problems with a component specifically used for optional inputs [1]. [1]: shadcn-ui/ui#410 (comment)
Optional inputs in controlled forms are problematic, because (1) Specifying default values for them in the `useForm` hook leads to unnecessary payload sent from the form, so rather keep them as `undefined`, which means the corresponding parameter is not included in the payload. (2) Leaving them without default values causes a React warning about a component transferring from uncontrolled to controlled state. Alleviate these problems with a component specifically used for optional inputs [1]. [1]: shadcn-ui/ui#410 (comment)
Here's my solution:
I tried a bunch of other solutions, but this one was the one that worked best. I didn't change anything in the Form component for this. Some form items are controlled (empty strings), other uncontrolled (the ones that are numbers are undefined) and React doesn't complain. I'm happy (although if this is a bad solution, do let me know....) Edit: not only that, but the 'Expected number, received nan' messages are also gone. If this is an acceptable way to use the component could be added to the documentation Edit 2 [clarity]: reason why I wrapped the FormItem around the FormField component was to be able to use the FormItem context to get the field id. the other way around (FormItem inside FormField) i wasn't able to figure out how to pass the field id to the Input field |
Optional inputs in controlled forms are problematic, because (1) Specifying default values for them in the `useForm` hook leads to unnecessary payload sent from the form, so rather keep them as `undefined`, which means the corresponding parameter is not included in the payload. (2) Leaving them without default values causes a React warning about a component transferring from uncontrolled to controlled state. Alleviate these problems with a component specifically used for optional inputs [1]. [1]: shadcn-ui/ui#410 (comment)
Hi again Shadcn and congrats for continuing to improve your already awesome project!
I noticed that React throws the error
A component is changing an uncontrolled input to be controlled
when we start typing in a form input:Here is a fresh Next.js project to which I added the example form provided in the doc:
https://github.com/Zwyx/shadcn-ui-form-uncontrolled-input-demo
Simply start the project, open your browser's console, and type in the form. You should see the error being thrown.
The text was updated successfully, but these errors were encountered: