diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 9cd1ead75d..8c733a9c24 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,4 +1,5 @@ export * from './useActionHandlers'; +export * from './useAsyncActionHandler'; export * from './useBodyScrollLock'; export * from './useFileInput'; export * from './useFocusWithin'; diff --git a/src/hooks/useAsyncActionHandler/README.md b/src/hooks/useAsyncActionHandler/README.md new file mode 100644 index 0000000000..5fcff146df --- /dev/null +++ b/src/hooks/useAsyncActionHandler/README.md @@ -0,0 +1,89 @@ + + +# useAsyncActionHandler + + + +```tsx +import {useAsyncActionHandler} from '@gravity-ui/uikit'; +``` + +The `useAsyncActionHandler` hook wraps an asynchronous action handler to add a loading state to it. +Starts the loading process before executing the passed action and terminates the process after executing the action. +Returns the loading state and the wrapped action handler + +## Properties + +| Name | Description | Type | Default | +| :------ | :------------- | :---------------------------------------------: | :-----: | +| handler | action handler | `(...args: unknown[]) => PromiseLike;` | | + +## Result + +```ts +{ + isLoading: boolean; + handler: typeof handler; +} +``` + +Usage: + +```tsx +const action = useCallback(() => Promise.resolve(), []); + +const {isLoading, handler: handleAction} = useAsyncActionHandler({handler: action}); +``` + +### Examples + +Button with automatic loading during click handler execution + +```tsx +type ProgressButtonProps = { + onClick: (event: React.MouseEvent) => PromiseLike; +} & Exclude; + +export const ProgressButton = (props: ProgressButtonProps) => { + const {onClick, loading: providedIsLoading} = props; + + const {isLoading, handler: handleClick} = useAsyncActionHandler({handler: onClick}); + + return