Unhappy experience with checkboxes #1603
Replies: 1 comment 3 replies
-
Yes, standard schemas are a bit iffy with defaultValues. Notably, you need to inform typescript that your defaultValues aren't just an object, but a const defaultValues: z.input<typeof yourSchema> = { /* ... */ } However, as you probably noticed too, it has a hard time combining with const defaultValues: z.input<typeof formOpts.validators.onChange> = { /* ... */ } There's multiple issues and feature requests that address how standard schemas should interact. Some devs prefer standard schemas to be a partial of their defaultValues, others want the defaultValues to be a partial of the schemas ... There's likely a solution that can be good for everyone. // schemas.ts
export const schema = z.object({
enabled: z.stringbool().default(false),
})
export const formOpts = formOptions({
validators: {
onBlur: schema,
},
defaultValues: {
// simpler, and i'm happy if i don't have to do type assertions to widen the type
enabled: false,
},
})
type Thing = {
enabled: boolean
}
export function getEmptyFormValues(params: Thing): z.input<typeof schema> {
return {
// manage conversions here.
}
}
// form.tsx
const form = useForm({
...formOpts,
defaultValues: getEmptyFormValues(params)
}) |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
@tanstack/react-form: ^v1.14.0
Hi there, digging the library! and i've been slowly using it in place of RHF, but i feel it still has some warts, at least when, like me, it's used alongside Next.js Server Actions and Zod. Hopefully it's something i'm doing wrong and it can be better documented.
In this case the problem is with doing checkboxes right. I want:
<input type="checkbox" ...>
false
as fallbackonBlur
form-level validatoruseActionState
)Here's a quickly put together extract from my current working code, the best i could achieve after some hours:
As you can see i ended up having to deal with
enabled
as a string. Fine, ideally i'd love for the value to be a boolean but that i couldn't make it work.The problems here are ergonomic but also type-based. If for example i didn't make that type assertion on the default value then it complains because Zod (4) is allowing a "key optional"
enabled?: string | undefined
while indefaultValue
it's juststring | undefined
and that for some reason is a problem. As a related aside, i'm sure that something better can be done for DX if a standard schema validator is passed so that i don't have to have to be doing stuff likename: "" as string | null
.As a related aside, i'm sure that something better can be done for DX if a standard schema validator is passed so that i don't have to have to be doing stuff like
name: "" as string | null
.Among other things, the server validator just validating but not parsing means i still have to use my schema in the server action, and thus the validation is done twice, where the validator just helps with decoding the
FormData
(for which elsewhere i usezfd
ordecode-formdata
, and iirc you guys and gals use something like it too). The zod parsing also removes extraneous keys like$ACTION_REF_1
.To keep complaints short, here's what a much happier experience would look like for me:
So, sorry for the big post 😅 I'm just struggling with some use cases which i don't consider atypical at all. In some sense it's obviously caused by having to reconcile (client-heavy form libs) with (non-symmetric schemas) with (native HTML form inputs that have annoying behaviors) with (React/Next.js Server Actions).
I'm open to being told i'm holding it wrong! And thank you!
Beta Was this translation helpful? Give feedback.
All reactions