fix(react-form): use fresh FieldApi in current render on name change#2240
Conversation
When a field's `name` changes (e.g. a non-last item is removed from a stably-keyed array), `useField` created a new FieldApi via `setFieldApi` during render but continued the current render pass with the stale instance. React discards that pass, but the render prop still runs to completion once with the stale FieldApi, whose store derives `undefined` for the path that no longer exists at the old index. This briefly surfaces `state.value === undefined` for surviving array items, crashing render code that treats the value strictly. Adjust state during render but also use the freshly created FieldApi for the remainder of this render, so the field reads state at its current `name`. Keeps the setState-based identity (React Compiler safe) while restoring the pre-1.27.0 behavior. Closes TanStack#2238
📝 WalkthroughWalkthrough
ChangesFieldApi synchronization
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
crutchcorn
left a comment
There was a problem hiding this comment.
Interesting fix. Very subtle. Assuming tests fix, I'll merge. Thanks!
|
View your CI Pipeline Execution ↗ for commit 09b74ac
☁️ Nx Cloud last updated this comment at |
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2240 +/- ##
===========================================
- Coverage 90.35% 64.95% -25.41%
===========================================
Files 38 19 -19
Lines 1752 311 -1441
Branches 444 48 -396
===========================================
- Hits 1583 202 -1381
+ Misses 149 94 -55
+ Partials 20 15 -5 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/hot-sides-fetch.md:
- Line 5: Update the changeset note to mention that a fresh FieldApi is used
when either the form or field name changes, accurately covering both triggers
addressed by the implementation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4f6404e0-1ff7-457a-b6b0-2840a30beb3e
📒 Files selected for processing (1)
.changeset/hot-sides-fetch.md
| '@tanstack/react-form': patch | ||
| --- | ||
|
|
||
| Use fresh FieldApi in current render on name change |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Mention form changes as well
The implementation refreshes FieldApi when either form or name changes, but this changeset only documents name changes. Please update the note so the published changelog accurately describes the fix.
Proposed wording
-Use fresh FieldApi in current render on name change
+Use fresh FieldApi in current render on form or name change📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Use fresh FieldApi in current render on name change | |
| Use fresh FieldApi in current render on form or name change |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.changeset/hot-sides-fetch.md at line 5, Update the changeset note to
mention that a fresh FieldApi is used when either the form or field name
changes, accurately covering both triggers addressed by the implementation.
Closes #2238
Regression from #1893 (v1.27.0). On a
name/formchange,useFieldcallssetFieldApi(new FieldApi(...))during render but the current render keeps using the stalefieldApistate. React discards that render, yet the render prop still runs once against the stale FieldApi's store — which derivesundefinedfor an array index that no longer exists after a removal, crashing strict render code.Fix applies the canonical "adjust-state-during-render + local variable" pattern: build the new instance, use it for the rest of the current render, and still
setFieldApiit (keeping the setState identity #1893 introduced for React Compiler safety) — restoring pre-1.27.0 correctness.undefined; fails before, passes after.pnpm vitest run(react-form) → 126 passed, no type errors.Summary by CodeRabbit
undefinedwhen removing an item from a stably keyed, shifted (non-last) element.