Skip to content

Fix/numberfield format options input reset#9905

Open
Wonchang0314 wants to merge 2 commits intoadobe:mainfrom
Wonchang0314:fix/numberfield-format-options-input-reset
Open

Fix/numberfield format options input reset#9905
Wonchang0314 wants to merge 2 commits intoadobe:mainfrom
Wonchang0314:fix/numberfield-format-options-input-reset

Conversation

@Wonchang0314
Copy link
Copy Markdown

@Wonchang0314 Wonchang0314 commented Apr 10, 2026

Closes #1893
Related to #9899

Summary

When formatOptions is passed as an inline object literal (e.g. formatOptions={{ style: 'currency',
currency: 'USD' }}), every parent re-render creates a new object reference. This caused
useNumberFieldState to detect a "change" in formatOptions and overwrite the current inputValue with
the last committed number value — resetting whatever the user was typing mid-input.

This fix stabilizes the formatOptions reference inside useNumberFieldState using a useRef and a
shallow equality check. If the new formatOptions has the same key-value pairs as the previous one,
the old reference is reused, preventing a spurious inputValue reset. I though this approach is appropriate
because all values in Intl.NumberFormatOptions are primitives (strings, numbers, booleans), so
shallow equality is equivalent to deep equality.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

  1. Run the existing NumberField test suites to verify nothing is broken:
    yarn jest packages/react-aria-components/test/NumberField.test.js
    yarn jest packages/@adobe/react-spectrum/test/numberfield/NumberField.test.js
  2. The two new regression tests specifically cover this fix:
    - "does not reset input value when parent re-renders with same formatOptions content" — a parent
    component with its own state re-renders while formatOptions is an inline object literal; the typed
    value must be preserved.
    - "does not reset input during typing when re-rendered with same formatOptions content" — same
    scenario via the rerender helper.
  3. To manually verify: render a NumberField with formatOptions={{ style: 'currency', currency: 'USD'
    }} as an inline literal inside a component that re-renders on some other state change. Type a value
    without committing (no blur/Enter) and trigger the parent re-render — the typed value should no
    longer be reset.

🧢 Your Project:

@github-actions github-actions bot added the RAC label Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

useNumberField's formatOptions must be memo'ized

2 participants