T
TanStack2mo ago
like-gold

Form level isDefaultValue always false.

I have code like this in my form:
<form.Subscribe
selector={(state) => [state.canSubmit, state.isSubmitting, state.isDefaultValue]}
children={([canSubmit, isDefaultValue]) => (
<div>
{JSON.stringify({ canSubmit, isDefaultValue })}
</div>
)}
/>
<form.Subscribe
selector={(state) => [state.canSubmit, state.isSubmitting, state.isDefaultValue]}
children={([canSubmit, isDefaultValue]) => (
<div>
{JSON.stringify({ canSubmit, isDefaultValue })}
</div>
)}
/>
The isDefaultValue there is always false. I tried also doing reset inside useEffect, also with delay (setTimeout), with both keepDefaultValues true and false. Nothing changes. I tried to investigate which of the fields is not default:
render: function Render({ form, onUploadMedia, detail, subject, className }) {
for (const [k, v] of Object.entries(form.fieldInfo)) {
if (v.instance?.getMeta().isDefaultValue) {
continue;
}
console.log('!DBG', k, v.instance?.getMeta().isDefaultValue);
}

setTimeout(() => {
let allDefault = true;
for (const [k, v] of Object.entries(form.fieldInfo)) {
if (v.instance?.getMeta().isDefaultValue) {
continue;
}
allDefault = false;
console.log('!DBG 2000', k, v.instance?.getMeta().isDefaultValue);
}
console.log('!DBG ALL DEFAULT 2000', allDefault);
}, 2000);
render: function Render({ form, onUploadMedia, detail, subject, className }) {
for (const [k, v] of Object.entries(form.fieldInfo)) {
if (v.instance?.getMeta().isDefaultValue) {
continue;
}
console.log('!DBG', k, v.instance?.getMeta().isDefaultValue);
}

setTimeout(() => {
let allDefault = true;
for (const [k, v] of Object.entries(form.fieldInfo)) {
if (v.instance?.getMeta().isDefaultValue) {
continue;
}
allDefault = false;
console.log('!DBG 2000', k, v.instance?.getMeta().isDefaultValue);
}
console.log('!DBG ALL DEFAULT 2000', allDefault);
}, 2000);
And according to this, all fields are at their default value. Any idea what might be happening? My version of @tanstack/react-form is 1.14.1
10 Replies
quickest-silver
quickest-silver2mo ago
could you share your form hook? The snippet that creates useAppForm
like-gold
like-goldOP2mo ago
quickest-silver
quickest-silver2mo ago
I see that I worded the previous message poorly. I don't see anything noteworthy here, but I was looking for the following:
// this here. Maybe something changes the default value?
const form = useAppForm({ defaultValues, /* ... */ });

<YourWithFormFromAbove form={form} />
// this here. Maybe something changes the default value?
const form = useAppForm({ defaultValues, /* ... */ });

<YourWithFormFromAbove form={form} />
because in the code, isDefaultValue is as you expect. A check for every field and seeing if isDefaultValue is true
like-gold
like-goldOP2mo ago
I see. It has structure like this:
function useMyForm({ data, onSubmit, ... }) {
const form = useAppForm({
defaultValues: transformData(data);
onSubmit: ...
});
return form;
}
function useMyForm({ data, onSubmit, ... }) {
const form = useAppForm({
defaultValues: transformData(data);
onSubmit: ...
});
return form;
}
Then in another component I do:
const data = useSuspenseQuery(...);
const form = useMyForm({data});
return <MyFormRenderer form={form} />
const data = useSuspenseQuery(...);
const form = useMyForm({data});
return <MyFormRenderer form={form} />
Right, but if any of the fields changed, they would have isDefaultValue false, right? What I find strange is the inconsistency between the field-level isDefaultValue and form level isDefaultValue. Is there some other state than the state covered by this?
for (const [k, v] of Object.entries(form.fieldInfo)) {
if (v.instance?.getMeta().isDefaultValue) {
continue;
}
console.log('!DBG', k, v.instance?.getMeta().isDefaultValue);
}
for (const [k, v] of Object.entries(form.fieldInfo)) {
if (v.instance?.getMeta().isDefaultValue) {
continue;
}
console.log('!DBG', k, v.instance?.getMeta().isDefaultValue);
}
quickest-silver
quickest-silver2mo ago
The internal state is
const fieldMetaValues = Object.values(currFieldMeta).filter(Boolean)
const isDefaultValue = fieldMetaValues.every((field) => field.isDefaultValue)
const fieldMetaValues = Object.values(currFieldMeta).filter(Boolean)
const isDefaultValue = fieldMetaValues.every((field) => field.isDefaultValue)
the hook creation also looks normal ... strange. try checking form.fieldMetaDerived.state instead of fieldInfo
like-gold
like-goldOP2mo ago
Ok, plot thickens! 😄 I added this:
render: function Render({ form, onUploadMedia, detail, subject, className }) {
const state = useStore(form.store, (state) => state);
const formIsDefault = useStore(form.store, (state) => state.isDefaultValue);
useEffect(() => {
let isDefaultValue = true;
for (const [k, v] of Object.entries(form.fieldMetaDerived.state)) {
if (!v.isDefaultValue) {
console.log('!XXX FIELD IS NOT DEFAULT', k);
isDefaultValue = false;
continue;
}
}
console.log('!DBG ALL FIELDS ARE DEFAULT', isDefaultValue);
console.log('!DBG FORM IS DEFAULT', state.isDefaultValue, formIsDefault);
}, [state, formIsDefault]);
render: function Render({ form, onUploadMedia, detail, subject, className }) {
const state = useStore(form.store, (state) => state);
const formIsDefault = useStore(form.store, (state) => state.isDefaultValue);
useEffect(() => {
let isDefaultValue = true;
for (const [k, v] of Object.entries(form.fieldMetaDerived.state)) {
if (!v.isDefaultValue) {
console.log('!XXX FIELD IS NOT DEFAULT', k);
isDefaultValue = false;
continue;
}
}
console.log('!DBG ALL FIELDS ARE DEFAULT', isDefaultValue);
console.log('!DBG FORM IS DEFAULT', state.isDefaultValue, formIsDefault);
}, [state, formIsDefault]);
The output is:
!DBG ALL FIELDS ARE DEFAULT true
!DBG FORM IS DEFAULT true true
!DBG ALL FIELDS ARE DEFAULT true
!DBG FORM IS DEFAULT true true
So in the useEffect hook, all is good. It's just the subscribe where it isDefaultValue is false and isDirty is true.
quickest-silver
quickest-silver2mo ago
hold up ... your selector and destructuring ... you named isSubmitting a variable called isDefaultValue
like-gold
like-goldOP2mo ago
omg I am so sorry to have wasted your time 😐
quickest-silver
quickest-silver2mo ago
no worries, I missed it too :KEKW: classic JavaScript moment though. If you ask me, if your destructuring array is not the same size as the input it ought to throw an error
like-gold
like-goldOP2mo ago
Changed it to object right away to avoid future mistake like this 😄

Did you find this page helpful?