T
TanStack5mo ago
stormy-gold

Incorrect type for field.state.meta.errors?

When my form first renders, field.state.meta.errors is undefined when the Typescript type argues it is always an array. I have a simple form with two fields which are validated with zod.
const productSchema = z.object({
name: z.string().min(1, "A name is required"),
allowance: z
.number()
.min(1, "Allowance must be at least 1")
.int("Allowance must be an integer"),
});

const form = useForm({
defaultValues: {
name: "Dataset Storage",
allowance: 1000,
},
validators: {
onChange: productSchema,
},
})
const productSchema = z.object({
name: z.string().min(1, "A name is required"),
allowance: z
.number()
.min(1, "Allowance must be at least 1")
.int("Allowance must be an integer"),
});

const form = useForm({
defaultValues: {
name: "Dataset Storage",
allowance: 1000,
},
validators: {
onChange: productSchema,
},
})
Then the react component
<form.Field name="name">
{(field) => (
<TextField
autoFocus
error={field.state.meta.errors.length > 0}
helperText={field.state.meta.errors.map((error) => error?.message)[0]}
label="Name"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
)}
</form.Field>
<form.Field name="name">
{(field) => (
<TextField
autoFocus
error={field.state.meta.errors.length > 0}
helperText={field.state.meta.errors.map((error) => error?.message)[0]}
label="Name"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
)}
</form.Field>
errors on both the errors and helperText props because I'm accessing on undefined.
Unhandled Runtime Error

TypeError: field.state.meta.errors is undefined
Unhandled Runtime Error

TypeError: field.state.meta.errors is undefined
Yet, Typescript argues it's an array. What's going on with the tanstack/form types here?
6 Replies
quickest-silver
quickest-silver5mo ago
Seems like you need to use the store here to get the errors in a reactive way, otherwise they might be stale.
const errors = useStore(field.store, (state) => state.meta.errors);
const errors = useStore(field.store, (state) => state.meta.errors);
solid-orange
solid-orange5mo ago
not sure if the reactivity is the issue here, but likely something with the first mount. Can you reproduce this issue on stackblitz? I usually see this undefined stuff when accessing from form.fieldInfo directly, but this is the first time I see it happen from a field
stormy-gold
stormy-goldOP5mo ago
Hmm this is very weird. The component with the useForm mounts when the user selects a value in a select component. This component appears in two places in the app. It's the same component and Jotai is used to handle the state. When the select component close to the form changes, the form renders without error. When I use the other select, this error appears.
stormy-gold
stormy-goldOP5mo ago
Ok managed to put together a repro. https://stackblitz.com/edit/vitejs-vite-nuuv84ts?file=src%2FApp.tsx This matches my setup well though. Two ways to make the form mount: 1. A button that lies next to the form component wrapper (works normally) 2. A button that lives in a diaglog (causes an error) (Refresh the page between each button option) Each button changes state managed by Jotai which leads to the conditional render of the Form.
Oliver Dudgeon
StackBlitz
Vitejs - Vite (forked) - StackBlitz
Next generation frontend tooling. It's fast!
solid-orange
solid-orange5mo ago
how strange it's not the first mount that has the undefined error
No description
stormy-gold
stormy-goldOP4mo ago
So is the value changing on re-render or is the form unmounting and then remounting with a value of undefined? And any ideas of why the two flows lead to different results? Is it worth creating a GitHub issue for this?

Did you find this page helpful?