T
TanStack•4mo ago
plain-purple

What's the recommended way to handle hidden fields?

I have a checkbox that, if checked, will make another text field appear. The zod validation will make use of .superRefine to require the text input value only if the checkbox is checked (its field as a value of true). I noticed that depending on how I hide the text field, the meta (and the errors) may not be up-to-date. Here some relevant code:
const invoiceEmailSameOrDifferent = useStore(form.store, (state) => state.values.invoiceEmailSameOrDifferent); // values are 'same' of 'different'

// radio buttons updating the value for invoiceEmailSameOrDifferent here

{invoiceEmailSameOrDifferent === 'different' && (
<form.Field
name="invoiceEmail"
children={(field) => {
return (
<>
<input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
<FieldInfo field={field} />
</>
);
}}
/>
)}
<div hidden={invoiceEmailSameOrDifferent !== 'different'}>
{<form.Field
name="invoiceEmail"
children={(field) => {
return (
<>
<input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
<FieldInfo field={field} />
</>
);
}}
/>}
</div>
const invoiceEmailSameOrDifferent = useStore(form.store, (state) => state.values.invoiceEmailSameOrDifferent); // values are 'same' of 'different'

// radio buttons updating the value for invoiceEmailSameOrDifferent here

{invoiceEmailSameOrDifferent === 'different' && (
<form.Field
name="invoiceEmail"
children={(field) => {
return (
<>
<input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
<FieldInfo field={field} />
</>
);
}}
/>
)}
<div hidden={invoiceEmailSameOrDifferent !== 'different'}>
{<form.Field
name="invoiceEmail"
children={(field) => {
return (
<>
<input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
<FieldInfo field={field} />
</>
);
}}
/>}
</div>
In the first case I am not even mounting <form.Field /> while in the second case, I am using the hidden attribute of HTML to hide the input, but the TSF Field is always mounted/instatiated. I noticed that sometimes the error is not displayed in the first case, meta.errors is empty. It kind of makes sense to me, so is hidden the recommended way to handle hidden fields in TSF?
9 Replies
fascinating-indigo
fascinating-indigo•4mo ago
This is somewhat related to this issue: https://github.com/TanStack/form/issues/1460 Essentially, fields currently do not check global errors on mount which can cause issues with conditional rendering. It may be worth subscribing to this issue to stay up to date on it, but for now, the hidden property sounds like the better option
GitHub
Array subfields missing errors in fieldMeta Ā· Issue #1460 Ā· TanSt...
Describe the bug When a user pushes a field using field.pushValue or form.pushFieldValue, errors for the subfields are missing from fieldMeta. This leads to a really bad state if the new subfield h...
plain-purple
plain-purpleOP•4mo ago
Thanks again Luca! šŸ™‚
rare-sapphire
rare-sapphire•4w ago
So I'm running into the same issue here, and was curious if going with hidden (keeping fields mounted) is the recommended approach over conditional rendering? I see there haven't been updates on the GitHub issue. Is this more of a React issue than a TanStack Form issue? @Luca | LeCarbonator I realized that many of the issues I was experiencing (that you helped me with earlier this week) were due to my form having multiple dynamic sections. For example, imagine a toggle like "Did you travel for this meeting?" that shows/hides 20+ fields based on the answer. I found that when I defaulted to "Yes" (mounting components immediately), many of my issues disappeared... šŸ˜• Is the general recommendation to avoid conditional mounting of form fields entirely and stick with hidden attributes instead?
fascinating-indigo
fascinating-indigo•4w ago
mounting and unmounting fields means they unsubscribe and resubscribe a lot. Since it's headless, you can choose to have conditional UI rendering instead while keeping the field mounted. Overall, I don't think the documentation brings that up a lot, and it probably should ... Besides, we have some bugs related to mounting fields too early / too late at the moment, so this needs some work either way
rare-sapphire
rare-sapphire•4w ago
Yeah I haven’t been able to get errors to appear consistently when unmounting/remounting. It normally requires that a user modify a field after it’s been mounted, and then all of the errors for the form appear. Would be happy to throw together a StackBlitz if that’s helpful. But otherwise if it’s a well known issue—that’s cool too. When it comes to the mounting fields too early/too late (which is what’s happening to me), are there any work arounds? Or is the ā€œhiddenā€ option the best workaround until that’s resolved?
fascinating-indigo
fascinating-indigo•4w ago
well, the workaround should be that the field is mounted once and the UI callback is the one being conditional so the part in children
- {myCondition && <form.Field ... />}
+ <form.Field ...
+ children={(field) => myCondition ? ... : null}>
- {myCondition && <form.Field ... />}
+ <form.Field ...
+ children={(field) => myCondition ? ... : null}>
rare-sapphire
rare-sapphire•4w ago
Oh interesting I’ve defiantly been conditioning rendering entire divs that render based on a value I’ve subscribed to in the form. Never thought about conditionally rendering the child. Though, that could definitely get a bit hairy with tons of fields… appreciate the insight! Might stick with the hidden approach for now šŸ˜„
fascinating-indigo
fascinating-indigo•4w ago
honestly? it ought to not make a difference, but here we are (for now)
rare-sapphire
rare-sapphire•4w ago
All good! I’ll keep an eye on this, and the release notes and just do some refactoring later. The library is so great that I can deal with these little things in the meantime

Did you find this page helpful?