psychedelicious 3a0ec635c9 feat(ui): add eslint rule react/jsx-no-bind
This rule enforces no arrow functions in component props. In practice, it means all functions passed as component props must be wrapped in `useCallback()`.

This is a performance optimization to prevent unnecessary rerenders.

The rule is added and all violations have been fixed, whew!
2023-11-13 10:01:14 +11:00

94 lines
2.1 KiB
TypeScript

import {
AlertDialog,
AlertDialogBody,
AlertDialogContent,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogOverlay,
forwardRef,
useDisclosure,
} from '@chakra-ui/react';
import {
cloneElement,
memo,
ReactElement,
ReactNode,
useCallback,
useRef,
} from 'react';
import { useTranslation } from 'react-i18next';
import IAIButton from './IAIButton';
type Props = {
acceptButtonText?: string;
acceptCallback: () => void;
cancelButtonText?: string;
cancelCallback?: () => void;
children: ReactNode;
title: string;
triggerComponent: ReactElement;
};
const IAIAlertDialog = forwardRef((props: Props, ref) => {
const { t } = useTranslation();
const {
acceptButtonText = t('common.accept'),
acceptCallback,
cancelButtonText = t('common.cancel'),
cancelCallback,
children,
title,
triggerComponent,
} = props;
const { isOpen, onOpen, onClose } = useDisclosure();
const cancelRef = useRef<HTMLButtonElement | null>(null);
const handleAccept = useCallback(() => {
acceptCallback();
onClose();
}, [acceptCallback, onClose]);
const handleCancel = useCallback(() => {
cancelCallback && cancelCallback();
onClose();
}, [cancelCallback, onClose]);
return (
<>
{cloneElement(triggerComponent, {
onClick: onOpen,
ref: ref,
})}
<AlertDialog
isOpen={isOpen}
leastDestructiveRef={cancelRef}
onClose={onClose}
isCentered
>
<AlertDialogOverlay>
<AlertDialogContent>
<AlertDialogHeader fontSize="lg" fontWeight="bold">
{title}
</AlertDialogHeader>
<AlertDialogBody>{children}</AlertDialogBody>
<AlertDialogFooter>
<IAIButton ref={cancelRef} onClick={handleCancel}>
{cancelButtonText}
</IAIButton>
<IAIButton colorScheme="error" onClick={handleAccept} ml={3}>
{acceptButtonText}
</IAIButton>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialogOverlay>
</AlertDialog>
</>
);
});
export default memo(IAIAlertDialog);