From 93ba6f6e68a19a0f4245476f5eb3a957485c94c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9F=E8=B4=A4?= Date: Thu, 23 Jun 2022 11:18:15 +0800 Subject: [PATCH 1/3] add should alway use option value --- tests/hooks.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/hooks.test.js b/tests/hooks.test.js index 7136e5a0..c28f96ff 100644 --- a/tests/hooks.test.js +++ b/tests/hooks.test.js @@ -251,6 +251,31 @@ describe('hooks', () => { fireEvent.mouseEnter(container.querySelector('span')); expect(onChange).toHaveBeenCalledWith(2, 1); }); + + it('should alway use option value', () => { + const onChange = jest.fn(); + + const Test = ({ value }) => { + const [mergedValue, setMergedValue] = useMergedState(undefined, { + value, + onChange, + }); + return ( + { + setMergedValue(12); + }} + > + {mergedValue} + + ); + }; + + const { container } = render(); + fireEvent.click(container.querySelector('span')); + + expect(container.textContent).toBe('1'); + }); }); describe('useLayoutEffect', () => { From 6725d6e46f40ff5166ed3f7a4e39bb8b627b8e45 Mon Sep 17 00:00:00 2001 From: zombiej Date: Thu, 23 Jun 2022 11:55:23 +0800 Subject: [PATCH 2/3] fix: merge logic --- src/hooks/useMergedState.ts | 5 ++--- tests/hooks.test.js | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/hooks/useMergedState.ts b/src/hooks/useMergedState.ts index 88c27c60..81c17146 100644 --- a/src/hooks/useMergedState.ts +++ b/src/hooks/useMergedState.ts @@ -70,9 +70,8 @@ export default function useMergedState( return [finalValue, source, finalValue]; }); - const postMergedValue = postState - ? postState(mergedValue[0]) - : mergedValue[0]; + const chosenValue = value ?? mergedValue[0]; + const postMergedValue = postState ? postState(chosenValue) : chosenValue; // ======================= Sync ======================= useUpdateEffect(() => { diff --git a/tests/hooks.test.js b/tests/hooks.test.js index c28f96ff..15a0bef4 100644 --- a/tests/hooks.test.js +++ b/tests/hooks.test.js @@ -201,6 +201,9 @@ describe('hooks', () => { setMergedValue(v => v + 1); setMergedValue(v => v + 1); }} + onMouseEnter={() => { + setMergedValue(1); + }} > {mergedValue} @@ -217,6 +220,8 @@ describe('hooks', () => { expect(onChange).not.toHaveBeenCalled(); // Click update + rerender(); + fireEvent.mouseEnter(container.querySelector('span')); fireEvent.click(container.querySelector('span')); expect(container.textContent).toEqual('3'); expect(onChange).toHaveBeenCalledWith(3, 1); From f8c0305d1996862ec500f782adb54118595461fa Mon Sep 17 00:00:00 2001 From: zombiej Date: Thu, 23 Jun 2022 12:00:00 +0800 Subject: [PATCH 3/3] chore: use fun --- src/hooks/useMergedState.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/hooks/useMergedState.ts b/src/hooks/useMergedState.ts index 81c17146..69130ada 100644 --- a/src/hooks/useMergedState.ts +++ b/src/hooks/useMergedState.ts @@ -30,6 +30,11 @@ const useUpdateEffect: typeof React.useEffect = (callback, deps) => { }, []); }; +/** We only think `undefined` is empty */ +function hasValue(value: any) { + return value !== undefined; +} + /** * Similar to `useState` but will use props value if provided. * Note that internal use rc-util `useState` hook. @@ -50,10 +55,10 @@ export default function useMergedState( let finalValue: T = undefined; let source: Source; - if (value !== undefined) { + if (hasValue(value)) { finalValue = value; source = Source.PROP; - } else if (defaultValue !== undefined) { + } else if (hasValue(defaultValue)) { finalValue = typeof defaultValue === 'function' ? (defaultValue as any)() @@ -70,7 +75,7 @@ export default function useMergedState( return [finalValue, source, finalValue]; }); - const chosenValue = value ?? mergedValue[0]; + const chosenValue = hasValue(value) ? value : mergedValue[0]; const postMergedValue = postState ? postState(chosenValue) : chosenValue; // ======================= Sync =======================