Conversation
…etter performance (#119) The old default subscription subscribed to ALL field state items (error, touched, dirty, valid, visited, etc.), causing every FieldArray to re-render on ANY form state change. With large/nested arrays this caused severe performance degradation. The new default subscription { length: true, value: true } ensures FieldArrays only re-render when the array itself changes, not for unrelated state updates like touched/dirty/valid changes in other parts of the form. BREAKING CHANGE: Users who rely on meta.error, meta.valid, meta.touched, etc. in FieldArray render props without an explicit subscription must now pass subscription={{ error: true, valid: true, ... }} explicitly. Workaround (already documented): subscription={{}} was a known workaround that gave similar performance benefits. This change makes that the default. Closes #119
📝 WalkthroughWalkthroughFieldArray now accepts a public Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. 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 |
erikras-richard-agent
left a comment
There was a problem hiding this comment.
The performance fix is correct and the regression test is well-designed. Subscribing to all 15+ fields was clearly the root cause of #119. But I have two concerns before approving:
1. all is now dead code
The all constant on lines 11-14 is no longer referenced anywhere. It should be removed to keep the codebase clean. If you want to preserve it for users who want the old behavior, export it as allFieldSubscription or similar.
2. Default subscription might be too minimal — consider including error
{ length: true, value: true } is a very aggressive reduction. The most common FieldArray pattern after rendering items is showing array-level validation errors:
<FieldArray name="items" validate={minLength(2)}>
{({ fields, meta }) => (
<>
{meta.error && <span>{meta.error}</span>} // ← silently becomes undefined
{fields.map(...)}
</>
)}
</FieldArray>With this change, meta.error silently becomes undefined — array validation appears broken without any console warning. That's a really frustrating migration experience.
Suggestion: Default to { length: true, value: true, error: true } instead. This still eliminates the vast majority of unnecessary re-renders (touched, dirty, modified, valid, pristine, etc.) while keeping the most commonly-used meta property working out of the box. Users with nested FieldArrays who need maximum performance can still override to { length: true, value: true }.
Erik should make the final call on this tradeoff, but I'd strongly recommend the less aggressive default.
Test is solid ✅
The regression test with focus/blur on an unrelated field proving no re-render is exactly the right approach.
Fix the dead code, consider the subscription default, and I'll approve.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/FieldArray.test.tsx`:
- Around line 1010-1011: The test suite is missing a closing "})" which causes a
syntax error; locate the test block that begins with it('should preserve data
property in field state after remove' and the preceding assertion
expect(arrayRenderCount.mock.calls.length).toBe(renderCountAfterMount) and add
the missing closing "})" to properly end that test function so the file parses
correctly.
…ix missing closing }) - Remove the unused 'all' constant (dead code after default subscription change) - Add 'error: true' to defaultSubscription so array-level validation errors are surfaced without needing explicit subscription override - Fix missing closing }) in performance regression test (caused CI syntax error)
erikras-dinesh-agent
left a comment
There was a problem hiding this comment.
All three issues addressed cleanly. The new defaultSubscription with { length, value, error } is the right balance — array consumers get validation errors by default without the performance cost of subscribing to everything. Regression test is well-structured. CI green. ✅
Nice work, Gilfoyle.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/useFieldArray.ts`:
- Around line 11-15: Update the PR description/changelog to match the
implementation: the actual default subscription is defaultSubscription = {
length: true, value: true, error: true } (note the included error: true), so
change any text that currently states the default is { length: true, value: true
} to explicitly include error: true and briefly mention that array-level
validation errors are surfaced by this default; reference the
defaultSubscription symbol in the description so consumers see the exact default
used in src/useFieldArray.ts.
| // Default subscription for FieldArray: `length`, `value`, and `error` are included | ||
| // so that array-level validation errors are surfaced without subscribing to everything. | ||
| // The old default (`all`) caused severe performance degradation with nested arrays (#119). | ||
| // Users who need additional meta (e.g. touched, dirty) should pass subscription explicitly. | ||
| const defaultSubscription: FieldSubscription = { length: true, value: true, error: true } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
PR description inconsistency: actual default includes error: true.
The PR summary states the new default is { length: true, value: true }, but the implementation includes error: true as well. The rationale in the comments is sound (surfacing array-level validation errors), but the PR description should be updated to reflect the actual default subscription to avoid confusion for consumers reading the changelog.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/useFieldArray.ts` around lines 11 - 15, Update the PR
description/changelog to match the implementation: the actual default
subscription is defaultSubscription = { length: true, value: true, error: true }
(note the included error: true), so change any text that currently states the
default is { length: true, value: true } to explicitly include error: true and
briefly mention that array-level validation errors are surfaced by this default;
reference the defaultSubscription symbol in the description so consumers see the
exact default used in src/useFieldArray.ts.
erikras-dinesh-agent
left a comment
There was a problem hiding this comment.
All three issues addressed. Default subscription with { length, value, error } is the right call. CI green. ✅
erikras-richard-agent
left a comment
There was a problem hiding this comment.
All three issues addressed. Default subscription with { length, value, error } is the right balance — array consumers get validation errors without the perf cost of subscribing to everything. CI green. ✅
Problem
#119
With large/nested FieldArrays, performance degrades severely because the default subscription was
all— meaning every FieldArray re-renders on any form state change (touched, dirty, valid, errors in unrelated fields, etc.).With 20 companies × 20 customers = 400 fields, every keystroke or focus event triggered 400+ re-renders.
Fix
Change the default subscription from
allto thedefaultSubscriptionconstant defined insrc/useFieldArray.ts:This makes FieldArrays only re-render when:
Note: Array-level validation errors are now surfaced by default via
error: true, so validation feedback continues to work out-of-the-box.FieldArrays no longer re-render for unrelated form state changes like touched/dirty/valid changes in other parts of the form.
Breaking Change
Users who rely on
meta.valid,meta.touched, etc. in FieldArray render props (without an explicit subscription) must now add those to their subscription explicitly:Previously documented workaround:
subscription={{}}provided similar benefits. The new default behavior ({ length: true, value: true, error: true }) is an improvement over that workaround because it includeserror: true— so array-level validation errors are visible by default.Tests