fix(core, react-form): Avoid set state error in React by avoiding set…
…ting default value until mount #1134
Due to the FieldApi constructor setting defaultValue in the constructor we violate: https://react.dev/link/setstate-in-render
UPDATE: We're going with option 2 below: moving set default value to mount function.
To avoid this I added a new flag which will prevent setting the default value within the constructor:
/**
* If true, the default value will not be set in the constructor.
*/
deferDefaultValue?: boolean
Within the react react-form package, we then set that flag true and do the following
const [fieldApi] = useState(() => {
const api = new FieldApi({
...opts,
form: opts.form,
name: opts.name,
deferDefaultValue: true, // Prevents https://react.dev/link/setstate-in-render by setting the default value after initial mount for React
})
//...
useIsomorphicLayoutEffect(() => {
if (fieldApi.options.defaultValue !== undefined) {
fieldApi.form.setFieldValue(
fieldApi.name,
fieldApi.options.defaultValue as never,
{
dontUpdateMeta: true,
},
)
}
}, [fieldApi])
Please let me know if you prefer this implementation ^^
Or a different implementation where we can simply move the following code into the mount function of the FieldApi class: https://github.com/TanStack/form/blob/135b88686bf9d10115828cd852ef2bd1201f5776/packages/form-core/src/FieldApi.ts#L999-L1003
This also solves the problem, though now we'd be affecting all other packages not just the React one. Tests pass for either implementation!
Thanks in advance!
View your CI Pipeline Execution ↗ for commit 6b912195a0be05f652d2d4fc3084a2e0087aef6b.
| Command | Status | Duration | Result |
|---|---|---|---|
nx affected --targets=test:sherif,test:knip,tes... |
✅ Succeeded | 2m 10s | View ↗ |
nx run-many --target=build --exclude=examples/** |
✅ Succeeded | 23s | View ↗ |
☁️ Nx Cloud last updated this comment at 2025-03-20 11:20:52 UTC
More templates
- @tanstack/form-example-angular-array
- @tanstack/form-example-angular-simple
- @tanstack/form-example-lit-simple
- @tanstack/form-example-lit-ui-libraries
- @tanstack/form-example-react-array
- @tanstack/form-example-react-compiler
- @tanstack/field-errors-from-form-validators
- @tanstack/form-example-react-large-form
- @tanstack/form-example-react-next-server-actions
- @tanstack/form-example-react-query-integration
- @tanstack/form-example-remix
- @tanstack/form-example-react-simple
- @tanstack/form-example-react-standard-schema
- @tanstack/form-example-react-tanstack-start
- @tanstack/form-example-react-ui-libraries
- @tanstack/form-example-solid-array
- @tanstack/form-example-solid-simple
- @tanstack/form-example-vue-array
- @tanstack/form-example-vue-simple
@tanstack/angular-form
npm i https://pkg.pr.new/@tanstack/angular-form@1250
@tanstack/form-core
npm i https://pkg.pr.new/@tanstack/form-core@1250
@tanstack/react-form
npm i https://pkg.pr.new/@tanstack/react-form@1250
@tanstack/lit-form
npm i https://pkg.pr.new/@tanstack/lit-form@1250
@tanstack/solid-form
npm i https://pkg.pr.new/@tanstack/solid-form@1250
@tanstack/vue-form
npm i https://pkg.pr.new/@tanstack/vue-form@1250
commit: 6b91219
Codecov Report
All modified and coverable lines are covered by tests :white_check_mark:
Project coverage is 88.86%. Comparing base (
caf2837) to head (6b91219). Report is 2 commits behind head on main.
Additional details and impacted files
@@ Coverage Diff @@
## main #1250 +/- ##
=======================================
Coverage 88.86% 88.86%
=======================================
Files 28 28
Lines 1275 1275
Branches 332 332
=======================================
Hits 1133 1133
Misses 127 127
Partials 15 15
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
🚀 New features to boost your workflow:
- ❄ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
- 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
I think I'd rather add the
defaultValuesetting inside ofmount.Also, ideally we don't have to set this flag to do that. If we set it inside of
mount, do all tests still pass on all adapters?
All tests passing on adapters, moved to simpler version of setting field value on mount function. Kept test within React that specifically tests the issue.
I think I'd rather add the
defaultValuesetting inside ofmount.Also, ideally we don't have to set this flag to do that. If we set it inside of
mount, do all tests still pass on all adapters?
Updated!
LGTM 🚀
Just had to fix the conflict🤟