Skip to content

Instantly share code, notes, and snippets.

@vimcaw
Last active September 20, 2022 07:48
Show Gist options
  • Save vimcaw/32745d0ac1342fbcb53bc453be3e36cd to your computer and use it in GitHub Desktop.
Save vimcaw/32745d0ac1342fbcb53bc453be3e36cd to your computer and use it in GitHub Desktop.
Automatically switch button loading state when onClick passes an asynchronous function or return a Promise on Ant Design
import React, { useState } from 'react';
import { Button } from 'antd';
import { ButtonProps } from 'antd/lib/button';
function isPromise(value: unknown): value is Promise<unknown> {
// ref: https://stackoverflow.com/questions/27746304/how-do-i-tell-if-an-object-is-a-promise
return (
typeof value === 'object' &&
value !== null &&
'then' in value &&
typeof (value as { then: unknown }).then === 'function'
);
}
export default function AsyncButton({
onClick,
loading: primitiveLoading,
...restProps
}: ButtonProps) {
const [isHandlingClick, setHandlingClick] = useState<boolean>(false);
return (
<Button
{...restProps}
loading={primitiveLoading === undefined ? isHandlingClick : primitiveLoading}
onClick={async (...args) => {
if (typeof onClick === 'function' && !isHandlingClick) {
const returnValue = onClick(...args) as unknown;
if (isPromise(returnValue)) {
// If "onClick" function return a Promise
// According to the status of Promise, switch loading automatically.
try {
setHandlingClick(true);
await returnValue;
setHandlingClick(false);
} catch (e) {
setHandlingClick(false);
throw e;
}
}
}
}}
/>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment