Fix: use Object.is() to prevent infinite loop when value is NaN (#11)#59
Fix: use Object.is() to prevent infinite loop when value is NaN (#11)#59
Conversation
…s NaN (#11) NaN !== NaN is always true in JavaScript. With the old !== comparison, when a FieldArray item value is NaN, OnChange would detect a 'change' on every render. If the OnChange callback triggered any re-render (e.g. form.change()), this created an infinite update loop. Fix: replace !== with Object.is() which correctly handles NaN equality (Object.is(NaN, NaN) === true). Closes #11
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughOnChange's equality check now uses Object.is() instead of !== to handle NaN and signed-zero semantics. A regression test was added to ensure an observed field initialized to NaN does not trigger repeated listener invocations or an infinite update loop when the callback updates a different field. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
erikras-richard-agent
left a comment
There was a problem hiding this comment.
Textbook fix. NaN !== NaN is always true → infinite loop. Object.is(NaN, NaN) is true → no false positive. One-line change, clean regression test that proves the loop doesn't happen.
CI ✅ CodeRabbit ✅ — Approved.
955f846
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/OnChange.test.tsx`:
- Around line 194-195: The test case that begins earlier in OnChange.test.tsx is
missing its closing "})" which causes the next test "it('should not call
listener on re-renders when value has not changed (`#7`)')" to be parsed
incorrectly; locate the open test block (the preceding it/describe around the
assertion expect(spy.mock.calls.length).toBeLessThanOrEqual(1)) and add the
missing closing brace and parenthesis to properly terminate the test before the
next it() starts so the test file's blocks are correctly balanced.
Addresses CodeRabbit feedback - the test case was missing its closing }) which caused the next test to be parsed incorrectly.
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/OnChange.test.tsx`:
- Around line 188-195: The test currently allows 0 calls by asserting
expect(spy.mock.calls.length).toBeLessThanOrEqual(1); change this to assert
exactly one call (e.g. expect(spy).toHaveBeenCalledTimes(1) or
expect(spy.mock.calls.length).toBe(1)) so the OnChange behavior (initial
callback firing on NaN vs undefined) is enforced; update the assertion in the
test that renders Wrapper and checks spy to use the exact-one-call expectation
to catch regressions where OnChange stops firing.
- Change toBeLessThanOrEqual(1) to toHaveBeenCalledTimes(1) - Add expect(spy).toHaveBeenCalledWith(NaN, undefined) - Prevents masking regressions where OnChange stops firing
|
Fixed — tightened assertion to |
Final Form initializes unregistered fields with empty string by default, so the first OnChange call receives (NaN, "") not (NaN, undefined).
erikras-richard-agent
left a comment
There was a problem hiding this comment.
Clean fix, solid test. Object.is() is exactly right for NaN comparison. Assertions are now tight — no silent regressions possible. CI green ✅. Approved.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Problem
#11
NaN !== NaNis alwaystruein JavaScript. TheOnChangeStatecomponent used!==to compare the current and previous values. When the watched field value isNaN:NaN !== NaN→true→ callback firesform.change('other', ...))OnChangeStatere-renders,useLayoutEffectrunsNaN !== NaN→trueagain → callback fires againFix
Replace
!==withObject.is()which correctly treatsNaNas equal to itself:Object.is(NaN, NaN) === true, so NaN values are correctly treated as unchanged.Test
Added a regression test that demonstrates the infinite loop with the old code and verifies it's fixed.
Summary by CodeRabbit
Bug Fixes
Tests