Skip to content

feat(useMergeOption): add useMergeOption #577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export { default as useDebounce } from './useDebounce';
export { default as useIntersectionObserver } from './useIntersectionObserver';
export { default as useList } from './useList';
export { default as useMeasure } from './useMeasure';
export { default as useMergeOption } from './useMergeOption';
export { default as useModal } from './useModal';
export { default as useTyping } from './useTyping';
export { default as useWindowSwitchListener } from './useWindowSwitchListener';
20 changes: 20 additions & 0 deletions src/useMergeOption/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { renderHook } from '@testing-library/react-hooks';

import useMergeOption from '..';

describe('Test useMergeOption', () => {
test('should return default value when state is false', () => {
const { result } = renderHook(() => useMergeOption(false, { day: true }));
expect(result.current).toEqual({ disabled: true, options: { day: true } });
});

test('should return default value when state is true', () => {
const { result } = renderHook(() => useMergeOption(true, { day: true }));
expect(result.current).toEqual({ disabled: false, options: { day: true } });
});

test('should return merged value when state is an object', () => {
const { result } = renderHook(() => useMergeOption({ day: false }, { day: true }));
expect(result.current).toEqual({ disabled: false, options: { day: false } });
});
});
48 changes: 48 additions & 0 deletions src/useMergeOption/demos/basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useState } from 'react';
import { Segmented } from 'antd';
import { useMergeOption } from 'dt-react-component';
import type { MergeOption } from 'dt-react-component/useMergeOption';

type ExampleState = MergeOption<{ day?: boolean }>;

export default function Basic() {
const [state, setState] = useState<ExampleState>(false);

const merged = useMergeOption(state, { day: true });

const getValue = () => {
if (state === false) return 0;
if (state === true) return 2;
return 1;
};
const setValue = (value: number) => {
setState([false, { day: false }, true][value]);
};

return (
<>
<label>Change value:</label>
<Segmented
value={getValue()}
options={[
{
label: 'false',
value: 0,
},
{
label: `{ day: false }`,
value: 1,
},
{
label: 'true',
value: 2,
},
]}
onChange={(val) => setValue(val as number)}
/>
<pre style={{ marginTop: 8, border: '1px solid #eee', padding: 8 }}>
{JSON.stringify(merged, null, 2)}
</pre>
</>
);
}
24 changes: 24 additions & 0 deletions src/useMergeOption/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: useMergeOption 合并配置项
group: Hooks
toc: content
---

# useMergeOption

## 何时使用

需要合并配置项

## 示例

<code src="./demos/basic.tsx" title="基础使用"></code>

## API

### Returns

| 参数 | 说明 | 类型 | 默认值 |
| -------- | -------------- | ------------------------------- | ------ |
| disabled | 是否禁用 | `boolean` | - |
| options | 合并后的配置项 | `T extends Record<string, any>` | - |
26 changes: 26 additions & 0 deletions src/useMergeOption/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useMemo } from 'react';

export type MergeOption<T extends Record<string, any>> = boolean | T;

export type ReturnMergeOption<T extends Record<string, any>> = {
disabled: boolean;
options: T;
};

export default function useMergeOption<T extends Record<string, any>>(
opt: MergeOption<T>,
defaultOpt?: T
): ReturnMergeOption<T> {
return useMemo(() => {
if (typeof opt === 'object' && !!opt) {
return {
disabled: false,
options: { ...defaultOpt, ...opt },
};
}
return {
disabled: !opt,
options: <T>{ ...defaultOpt },
};
}, [opt]);
}
Loading