diff --git a/src/index.ts b/src/index.ts index 861a84951..3c270867e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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'; diff --git a/src/useMergeOption/__tests__/index.test.ts b/src/useMergeOption/__tests__/index.test.ts new file mode 100644 index 000000000..e2de355d2 --- /dev/null +++ b/src/useMergeOption/__tests__/index.test.ts @@ -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 } }); + }); +}); diff --git a/src/useMergeOption/demos/basic.tsx b/src/useMergeOption/demos/basic.tsx new file mode 100644 index 000000000..213a65834 --- /dev/null +++ b/src/useMergeOption/demos/basic.tsx @@ -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(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 ( + <> + + setValue(val as number)} + /> +
+                {JSON.stringify(merged, null, 2)}
+            
+ + ); +} diff --git a/src/useMergeOption/index.md b/src/useMergeOption/index.md new file mode 100644 index 000000000..8c03b743a --- /dev/null +++ b/src/useMergeOption/index.md @@ -0,0 +1,24 @@ +--- +title: useMergeOption 合并配置项 +group: Hooks +toc: content +--- + +# useMergeOption + +## 何时使用 + +需要合并配置项 + +## 示例 + + + +## API + +### Returns + +| 参数 | 说明 | 类型 | 默认值 | +| -------- | -------------- | ------------------------------- | ------ | +| disabled | 是否禁用 | `boolean` | - | +| options | 合并后的配置项 | `T extends Record` | - | diff --git a/src/useMergeOption/index.ts b/src/useMergeOption/index.ts new file mode 100644 index 000000000..e42b59461 --- /dev/null +++ b/src/useMergeOption/index.ts @@ -0,0 +1,26 @@ +import { useMemo } from 'react'; + +export type MergeOption> = boolean | T; + +export type ReturnMergeOption> = { + disabled: boolean; + options: T; +}; + +export default function useMergeOption>( + opt: MergeOption, + defaultOpt?: T +): ReturnMergeOption { + return useMemo(() => { + if (typeof opt === 'object' && !!opt) { + return { + disabled: false, + options: { ...defaultOpt, ...opt }, + }; + } + return { + disabled: !opt, + options: { ...defaultOpt }, + }; + }, [opt]); +}