useConfirmOnClose.tsx 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { useCallback, useMemo, useState } from 'react'
  2. import useLatest from '../misc/useLatest'
  3. export interface ConfirmOnCloseModalProps {
  4. visible: boolean
  5. onClose: () => void
  6. onCancel: () => void
  7. }
  8. interface UseConfirmOnCloseProps {
  9. checkIsDirty: () => boolean
  10. onClose: () => void
  11. }
  12. export const useConfirmOnClose = ({ checkIsDirty, onClose }: UseConfirmOnCloseProps) => {
  13. const [visible, setVisible] = useState(false)
  14. const checkIsDirtyRef = useLatest(checkIsDirty)
  15. const onCloseRef = useLatest(onClose)
  16. const confirmOnClose = useCallback(() => {
  17. if (checkIsDirtyRef.current()) {
  18. setVisible(true)
  19. } else {
  20. onCloseRef.current()
  21. }
  22. // eslint-disable-next-line react-hooks/exhaustive-deps
  23. }, [])
  24. const handleOpenChange = useCallback(
  25. (open: boolean) => {
  26. if (!open) {
  27. confirmOnClose()
  28. }
  29. },
  30. [confirmOnClose]
  31. )
  32. const onConfirm = useCallback(() => {
  33. setVisible(false)
  34. onCloseRef.current()
  35. // eslint-disable-next-line react-hooks/exhaustive-deps
  36. }, [])
  37. const onCancel = useCallback(() => {
  38. setVisible(false)
  39. }, [])
  40. const modalProps: ConfirmOnCloseModalProps = useMemo(
  41. () => ({
  42. visible,
  43. onClose: onConfirm,
  44. onCancel,
  45. }),
  46. [visible, onConfirm, onCancel]
  47. )
  48. return useMemo(
  49. () => ({
  50. confirmOnClose,
  51. handleOpenChange,
  52. modalProps,
  53. }),
  54. [confirmOnClose, handleOpenChange, modalProps]
  55. )
  56. }