Skip to content

Commit a71a0a7

Browse files
authored
Prevent extra onChanges from useControlledState (#1480)
NaN !== NaN, but we can compare them using Object.is https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
1 parent 7326ad2 commit a71a0a7

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

packages/@react-stately/utils/src/useControlledState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export function useControlledState<T>(
3232
let setValue = useCallback((value, ...args) => {
3333
let onChangeCaller = (value, ...onChangeArgs) => {
3434
if (onChange) {
35-
if (stateRef.current !== value) {
35+
if (!Object.is(stateRef.current, value)) {
3636
onChange(value, ...onChangeArgs);
3737
}
3838
}

packages/@react-stately/utils/test/useControlledState.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,24 @@ describe('useControlledState tests', function () {
4848
expect(onChangeSpy).toHaveBeenLastCalledWith('newValue');
4949
});
5050

51+
it('using NaN will only trigger onChange once', () => {
52+
let onChangeSpy = jest.fn();
53+
let {result} = renderHook(() => useControlledState(undefined, undefined, onChangeSpy));
54+
let [value, setValue] = result.current;
55+
expect(value).not.toBeDefined();
56+
expect(onChangeSpy).not.toHaveBeenCalled();
57+
act(() => setValue(NaN));
58+
[value, setValue] = result.current;
59+
expect(value).toBe(NaN);
60+
expect(onChangeSpy).toHaveBeenCalledTimes(1);
61+
expect(onChangeSpy).toHaveBeenLastCalledWith(NaN);
62+
63+
act(() => setValue(NaN));
64+
[value, setValue] = result.current;
65+
expect(value).toBe(NaN);
66+
expect(onChangeSpy).toHaveBeenCalledTimes(1);
67+
});
68+
5169
it('can handle callback setValue behavior', () => {
5270
let onChangeSpy = jest.fn();
5371
let {result} = renderHook(() => useControlledState(undefined, 'defaultValue', onChangeSpy));

0 commit comments

Comments
 (0)