canSubmit is not set in state when provided to defaultState prop at form initialization
Describe the bug
I'm trying to create a read only version of a form in React. react-hook-form has the disabled prop in the UseForm prop which propagates to all fields and I hope a similar feature could be added to Tanstack form. I wanted to emulate a read only form by setting canSubmit to false in the defaultState option. Then, by checking if both canSubmit and isSubmitting are false, the form must be read only. I hope my understanding about how those two fields work is correct.
However, I found out that the value for canSubmit is ignored when provided to defaultState. A simple example is as follows:
const form = useForm({
defaultValues: {
firstName: '',
lastName: '',
},
defaultState: {
canSubmit: false,
},
});
console.log(form.state.canSubmit); // Evaluates to true
Your minimal, reproducible example
https://stackblitz.com/edit/tanstack-form-vzvauf?file=src%2Findex.tsx
Steps to reproduce
- Create a form object using the
useFormhook withdefaultState: { canSubmit: false }in the props. - Evaluate the resulting value of
form.state.canSubmit
Expected behavior
By submitting canSubmit: false in the defaultState, I expect the state after initialization to contain a false value for this property. The value is true however, which is not expected. If this is intentional, it is very counter-intuitive, but if this is unintentional then I think it needs fixing.
How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
- OS: Windows
- Browser: Chrome
- Version: 128
TanStack Form adapter
react-form
TanStack Form version
0.32.0
TypeScript version
No response
Additional context
No response
I tried the exact same thing.
@Balastrong answered the following in the Discord-Channel:
You shouldn't manually set canSubmit [via defaultState] as it's overridden by the form
[…] the entire defaultState object […] is undocumented and shouldn't be manually changed but it is used internally and for testing purposes
Thanks for the clarification, knowing that we shouldn't touch it is useful information. In that case I hope the docs can be updated to reflect this. Currently it does list defaultState as an option here without providing information that it should not be used.
To be fair, the docs you're pointing to are actually autogenerated and only really meant for deep dives and assistance in reading the codebase.
What guidance are you generally looking for here?
I'm not sure I understand your question. In my experience, the API exposed by a library is exposed specifically because it is made available to a user. The same goes for documentation for said API. When something is meant for development or testing, I see it is generally left out of the documentation, marked private, or is clearly indicated to be for internal use only (for example a field called internalState). That way it is made clear to a user not to touch those parts of the API. It is also why I found it interesting to hear that defaultState was for internal use only, even though it was mentioned in the API reference. Personally, I read API reference documentation quite a lot because it helps me get the most out of libraries, more than basic how-to guides.
Regardless, I totally understand that things like this are inevitable for libraries that haven't matured yet. When I installed this library, I expected there to be peculiarities that hadn't been fleshed out due to it being a pre-1.0 release. Still, I do think it can be helpful to mark those fields as internal one way or the other to prevent users like me making bug reports about parts of the API that are supposed to be internal and are thus not behaving as expected.
As for the specific reason this issue came up: I'm making a CRUD application and I hoped to populate the fields with the Form API in a read-only state. That way I could use the same layout for not only the C and U, but also the R. As I wrote in the original post, react-hook-form has a disabled prop that propagates it to all fields, which this library lacks. I had hoped to have found a work-around by setting canSubmit to false in defaultState, so that the state with both canSubmit and isSubmitting being false would resemble the state of a read-only form. But as defaultState turns out to be for internal use only and thus does not behave as one would expect, this work-around does not work.
While canSubmit should probably not be overwritten, I found the underlying issue causing this problem: https://github.com/TanStack/form/issues/1036
We're actively working on a fix right now as part of #1038. Closing in favor of 1036 so we can retain more technical internals discussions