Skip to content

Commit f3d1eaa

Browse files
fix: Should always merge (#316)
* add should alway use option value * fix: merge logic * chore: use fun Co-authored-by: 期贤 <[email protected]>
1 parent 997ff29 commit f3d1eaa

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

src/hooks/useMergedState.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ const useUpdateEffect: typeof React.useEffect = (callback, deps) => {
3030
}, []);
3131
};
3232

33+
/** We only think `undefined` is empty */
34+
function hasValue(value: any) {
35+
return value !== undefined;
36+
}
37+
3338
/**
3439
* Similar to `useState` but will use props value if provided.
3540
* Note that internal use rc-util `useState` hook.
@@ -50,10 +55,10 @@ export default function useMergedState<T, R = T>(
5055
let finalValue: T = undefined;
5156
let source: Source;
5257

53-
if (value !== undefined) {
58+
if (hasValue(value)) {
5459
finalValue = value;
5560
source = Source.PROP;
56-
} else if (defaultValue !== undefined) {
61+
} else if (hasValue(defaultValue)) {
5762
finalValue =
5863
typeof defaultValue === 'function'
5964
? (defaultValue as any)()
@@ -70,9 +75,8 @@ export default function useMergedState<T, R = T>(
7075
return [finalValue, source, finalValue];
7176
});
7277

73-
const postMergedValue = postState
74-
? postState(mergedValue[0])
75-
: mergedValue[0];
78+
const chosenValue = hasValue(value) ? value : mergedValue[0];
79+
const postMergedValue = postState ? postState(chosenValue) : chosenValue;
7680

7781
// ======================= Sync =======================
7882
useUpdateEffect(() => {

tests/hooks.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ describe('hooks', () => {
201201
setMergedValue(v => v + 1);
202202
setMergedValue(v => v + 1);
203203
}}
204+
onMouseEnter={() => {
205+
setMergedValue(1);
206+
}}
204207
>
205208
{mergedValue}
206209
</span>
@@ -217,6 +220,8 @@ describe('hooks', () => {
217220
expect(onChange).not.toHaveBeenCalled();
218221

219222
// Click update
223+
rerender(<Demo value={undefined} />);
224+
fireEvent.mouseEnter(container.querySelector('span'));
220225
fireEvent.click(container.querySelector('span'));
221226
expect(container.textContent).toEqual('3');
222227
expect(onChange).toHaveBeenCalledWith(3, 1);
@@ -251,6 +256,31 @@ describe('hooks', () => {
251256
fireEvent.mouseEnter(container.querySelector('span'));
252257
expect(onChange).toHaveBeenCalledWith(2, 1);
253258
});
259+
260+
it('should alway use option value', () => {
261+
const onChange = jest.fn();
262+
263+
const Test = ({ value }) => {
264+
const [mergedValue, setMergedValue] = useMergedState(undefined, {
265+
value,
266+
onChange,
267+
});
268+
return (
269+
<span
270+
onClick={() => {
271+
setMergedValue(12);
272+
}}
273+
>
274+
{mergedValue}
275+
</span>
276+
);
277+
};
278+
279+
const { container } = render(<Test value={1} />);
280+
fireEvent.click(container.querySelector('span'));
281+
282+
expect(container.textContent).toBe('1');
283+
});
254284
});
255285

256286
describe('useLayoutEffect', () => {

0 commit comments

Comments
 (0)