Skip to content

alert/confirm 사용 예제

dictionary-app은 브라우저 기본 confirm()/alert() 대신, 어디서든 호출해 Promise로 사용자의 선택을 돌려받는 confirmDialog/alertDialog 전역 함수를 쓴다.

  1. confirmDialog — 확인을 누르면 true, 취소하거나 바깥 영역을 클릭해 닫으면 false로 resolve된다.
    utils/confirmDialog.ts
    export const confirmDialog = (options: DialogOptions): Promise<boolean> => {
    return useDialogStore.getState().openDialog(options)
    }
  2. alertDialog — confirmDialog와 상태·렌더링을 그대로 공유하며, 취소 버튼만 숨긴 확인 버튼 하나짜리 형태다.
    utils/alertDialog.ts
    export type AlertDialogOptions = Omit<DialogOptions, 'cancelText' | 'showCancel'>
    export const alertDialog = (options: AlertDialogOptions): Promise<void> => {
    return useDialogStore
    .getState()
    .openDialog({...options, showCancel: false})
    .then(() => undefined)
    }
  1. App 루트에 한 번만 마운트해두면, 이후 어디서든 confirmDialog/alertDialog를 호출하는 것만으로 다이얼로그가 뜬다. role="alertdialog"로 렌더링한다.
    App.tsx
    export const App = () => {
    return (
    <QueryClientProvider client={queryClient}>
    <RouteConfig />
    <Toaster />
    <ActionDialog />
    <GlobalSpinner />
    </QueryClientProvider>
    )
    }
  2. options.showCancel이 false면 취소 버튼을 숨긴다(alertDialog가 내부적으로 이렇게 호출한다).
    components/organisms/action-dialog/ActionDialog.tsx
    export const ActionDialog = () => {
    const {isOpen, options, closeDialog} = useDialogStore()
    return (
    <Dialog.Root open={isOpen} onOpenChange={handleOpenChange} role="alertdialog">
    <Portal>
    <Dialog.Content>
    <Dialog.Header>
    <Dialog.Title>{options?.title}</Dialog.Title>
    </Dialog.Header>
    {options?.description && (
    <Dialog.Body>
    <Dialog.Description>{options.description}</Dialog.Description>
    </Dialog.Body>
    )}
    <Dialog.Footer>
    {options?.showCancel !== false && (
    <Button variant="outline" colorPalette="gray" handleClick={handleCancel}>
    {options?.cancelText ?? '취소'}
    </Button>
    )}
    <Button
    colorPalette={options?.confirmColorPalette ?? 'brand'}
    handleClick={handleConfirm}
    >
    {options?.confirmText ?? '확인'}
    </Button>
    </Dialog.Footer>
    </Dialog.Content>
    </Portal>
    </Dialog.Root>
    )
    }
  1. await로 결과를 기다렸다가, 취소면 그대로 종료한다.
    pages/word/domain/useDomain.ts
    const handleDeleteSelected = async () => {
    const confirmed = await confirmDialog({
    title: '도메인 삭제',
    description: `선택한 ${selectedDomains.length}건을 삭제하시겠습니까? 삭제한 데이터는 복구할 수 없습니다.`,
    confirmText: '삭제',
    confirmColorPalette: 'red',
    })
    if (!confirmed) {
    return
    }
    await deleteDomains(selectedDomains.map((domain) => domain.id))
    }
  2. confirmColorPalette로 삭제처럼 위험한 액션은 red, 일반 확인은 기본값(brand)을 쓴다.