How to async load defaultValues from a global state?
I should load my defaultValues for useAppForm from a global store.
However, i dont want to block the rendering of the form with a loading or a spinner, so i am doing this:
This works (even though i don't know if the recommended approach).
However, due to this form.validate(), all non-optional fields with null values shows the error, even tough error content has been guarded by the "field.state.meta.isTouched && !field.state.meta.isValid".
Is this an intended approach? Apparently setFieldValue marks fields touched by default.
Ps: i know setFieldValue has a dontUpdateMeta opt prop, but this seems to not only not marking isTouched: true but also would make form.validate('change') to have no effect.
This seems a much trivial usecase but I am might have not yet found an elegant way to handle it. Appreciate if anyone can shine some light! 🙂
23 Replies
xenial-black•3mo ago
Have you read through the async initial values section of the documentation? https://tanstack.com/form/latest/docs/framework/react/guides/async-initial-values
Async Initial Values | TanStack Form React Docs
Let's say that you want to fetch some data from an API and use it as the initial value of a form. While this problem sounds simple on the surface, there are hidden complexities you might not have thou...
xenial-black•3mo ago
if so, what were the issues with implementing it this way?
absent-sapphireOP•3mo ago
Thanks for you response @Luca | LeCarbonator
Yes. I have read it all a couple of times.
If you see the documentation, you will see that it loads the initial data from external using Ts query, in which can greatly control is loading state. Example is not loading from a global state.
In my case, I have a multi step form which makes no sense to load data on every step so I am fetching once and setting on a state.
I also don’t want to block the form rendering because in terms of UI I think makes no sense.
So here is the thing: how to asynchronous load from a state, for example while not blocking form rendering. I spent a few hours but honestly haven’t found a proper solution as I said.
Apparently form.setfieldvalue + form.validate should be the answer but these makes all fields touched which is not the case. I want to silently load the data.
Any thoughts @Luca | LeCarbonator ?
xenial-black•3mo ago
well, do
delivery_method
and recipient_name
cause a rerender? They should be able to be passed the same as in the documentation exampleabsent-sapphireOP•3mo ago
They would do yes!
But this comes to another problem. How to validate it? Since validate, onMount would have already been validated with initial data which was undefined?
Now you may notice where I am getting to.. right?
xenial-black•3mo ago
I'll see if I can create a stackblitz reproduction for experimenting
absent-sapphireOP•3mo ago
That would be great. I must say I never lazy at all 🙂
Once I post it is actually I have not found a proper solution for real 🙂
for sure I might have oversight some obvious solution, but that would be undocumented.
If you need any help call me anytime! Would be happy to help!
xenial-black•3mo ago
Async mounted validation is rather rare, so I can't think of a cleaner solution than the programmatic approach you provided.
https://stackblitz.com/edit/vitejs-vite-hrarbsuz?file=src%2FApp.tsx I've created a basic example of async state.
From what I can tell, it works as expected. I used the guard you provided (
field.state.meta.isTouched && !field.state.meta.isValid
) and email
does not show its error until it is changed.
Could you take a look at the reproduction? Perhaps I misunderstood your desired behaviour of showing errors.
If your desired behaviour is delivery_method
and recipient_name
to immediately show errors while other fields are unchanged, dontUpdateMeta
needs to be false (default). This will touch the fields it changed.
If your desired behaviour is delivery_method
and recipient_name
to not show errors immediately unless they're changed, then dontUpdateMeta
is the way to go. The errors are still generated, but are blocked from the user (see console)absent-sapphireOP•3mo ago
@Luca | LeCarbonator you actually were mislead by default behaviour. Will explain...
See your updated example:
https://stackblitz.com/edit/vitejs-vite-hnfl3pzc?file=src%2FApp.tsx
Its self explanatory, but check comments.
Matheus
StackBlitz
Asynchronous defaultValues with validation (duplicated) - StackBlitz
Next generation frontend tooling. It's fast!
xenial-black•3mo ago
I see now! The solution depends on what your submit button behaviour should be:
1. Async data is loaded, it is correct. The user did not change values yet. Should the submit button be enabled or disabled?
2. Async data is loaded, it is correct. The user changed other values. Should the submit button be enabled or disabled?
3. Async data is loaded, it has errors. Should they immediately show up?
One property that can help with this is
state.isPristine
. It informs you whether or not there are changed values in your form.
Alternatively, there is state.isDefaultValue
in case you want to check for non-persistent dirty (like in react-hook-form)
onMount
validation makes little sense here as your values are asynchronous. Feel free to remove it.
If we use onMount validaiton, then form load as canSubmit = false, because all initial values are undefined.Correct, so it's not useful for this form.
If we dont use onMount, then form load as canSubmit = true, even though it has not all values set
isPristine
and isDefaultValue
are the key to this. It depends on what your desired behaviour is though, so I changed the values to give visual feedback.
Some notes:
* canSubmit
is based on fields and their isValid
state, which means it's affected by dontUpdateMeta
* isPristine
is based on field meta, which means it's affected by dontUpdateMeta
* isDefaultValue
is a derived value determined from field.state.value
and defaultValues
, so it's always up to date regardless of dontUpdateMeta
https://stackblitz.com/edit/vitejs-vite-hixhvdfg?file=src%2FApp.tsxLeCarbonator
StackBlitz
Asynchronous defaultValues with validation (duplicated) - StackBlitz
Next generation frontend tooling. It's fast!
xenial-black•3mo ago
The async data was correct

xenial-black•3mo ago
The async data is incorrect. Note how the error is immediately visible in the last one since
isTouched: true

xenial-black•3mo ago
As an unconventional approach, this may also be worth looking into:
xenial-black•3mo ago

absent-sapphireOP•3mo ago
@Luca | LeCarbonator Thanks. Confess my head is spinning around on this.
The UI decisions i have made are the simplest and straight forward as possible:
- Async data is loaded, values are valid? Submit button enabled
- Any value invalid? Submit button disabled.
Is that simple as that - This is a very common usecase in the company forms.
I should not show any errors because most likely the values (when loaded) will be valid. So user will rightly know that button is disabled because of missing values. In terms of UI is not correct to print errors to the user since user has not even touched any field.
So about your examples: from what i understood, i should also only show render errors then isPristine is false, right?
But this is what makes it very confusing, because, lets consider when async data is incorrect example:
- DontUpdateMeta: true, canSubmit is true (?) while isPristine is true. I cannot rely on these to disable my submit button.
- DontUpdateMeta: false, canSubmit is false (correct), but isPristine is also false (so i cannot rely on this either).
I hope my usecase makes sense to you, but even considering isPristine and isDefaultValue, my brain is burning. Am I not seing something here?
xenial-black•3mo ago
Note
There appears to be an issue with stale The form must be submittable ( There appears to be an error with that as of
canSubmit
. I somehow managed to end up in a state where errors
is not empty, but canSubmit
is true. I'll investigate further and create a GitHub issue for it. It appears to be related to calling change validation on pristine forms.
Note that isValid
appears to be unaffected.
The requirements are:
* Async data must be loaded (!!user
)
* The user can submit without touching fields (!isPristine || isPristine
=> true
)
* The form renders immediately, async data is set later
* Validation must occur as soon as data is loaded
* The form must be valid (isValid
)
* canSubmit
)v1.12.3
. I'll investigate further.
We can conclude that the correct check for the submitButton is therefore disabled={!user || !isValid}
To summarize:
* when data is loaded, use setFieldValue
. We don't want to mark the field as touched, so use dontUpdateMeta: true
* after setting the new data, trigger on change validation. form.validate('change')
.
See the example here: https://stackblitz.com/edit/vitejs-vite-hixhvdfg?file=src%2FApp.tsx
I'm sorry that you had to encounter the bug like this. That was quite the time waster, but at least it's a known bug now.
As far as user experience is concerned, if the initial values take time to load, they will overwrite any values that the user wrote, so keep that in mindabsent-sapphireOP•3mo ago
Thanks so much @Luca | LeCarbonator !
So at the end canSubmit was unintendedly being marked as true even though it had errors. Nice catch!
I will use isValid for a while which seems to solve the issue.
Thanks once again!
xenial-black•3mo ago
thanks for the example! It should narrow down the cause. I'll link the issue here once it's created.
the difference between canSubmit and isValid is mostly with how they manage onMount errors and the
isSubmitting
state, so it should not matter for this use casefascinating-indigo•3mo ago
https://tanstack.com/form/latest/docs/framework/react/examples/next-server-actions?path=examples%2Freact%2Fnext-server-actions%2Fsrc%2Fapp%2Fclient-component.tsx
can someone explain why isSubmitting doesnt work properly?
React TanStack Form Next Server Actions Example | TanStack Form Docs
An example showing how to implement Next Server Actions in React using TanStack Form.
xenial-black•3mo ago
based on the ssr example, it‘s probably because isSubmitting checks for the execution of
onSubmit
which is essentially immediate
but I‘ve heard multiple times that it‘s unintuitive for nextjs. Could you list the expected behaviour and I‘ll see if it‘s possible to implement it?fascinating-indigo•3mo ago
I would like to see that isSubmitting:true during submit execution
even in example i should see ... when is Submitting
but it doesnt happen
fascinating-indigo•3mo ago
I change example and add delay in action
https://stackblitz.com/github/tanstack/form/tree/main/examples/react/next-server-actions?embed=1&theme=dark&preset=node&file=src/index.tsx
StackBlitz
Form Next Server Actions Example - StackBlitz
Run official live example code for Form Next Server Actions, created by Tanstack on StackBlitz
fascinating-indigo•3mo ago
it still not working
i would like to use isSubmitting but seems I have to use isPending from useActionState