Archive
useConfirm

useConfirm

window.confirm시 뜨는 모달을 직접 커스텀해서 유사하게 구현한 hooks입니다.

Example

Steps

Prerequisite

Install Package

npm install recoil

Add Recoil Settings

services/store/index.ts
import type { ReactNode } from 'react'
import { atom } from 'recoil'
 
const confirmState = atom<{ content: ReactNode; isOpen: boolean }>({
  key: 'confirmState',
  default: {
    content: '',
    isOpen: false
  }
})

Copy Code

services/hooks/index.tsx
import { useRecoilState, useResetRecoilState } from 'recoil'
 
let confirmCb: any
const useConfirm = () => {
  const [state, setState] = useRecoilState()
  const resetState = useResetRecoilState()
 
  const onConfirm = () => {
    confirmCb(true)
    resetState()
  }
 
  const onCancel = () => {
    confirmCb(false)
    resetState()
  }
 
  const confirm = (content: ReactNode): Promise<any> => {
    setState({ content, isOpen: true })
    return new Promise((resolve) => {
      confirmCb = resolve
    })
  }
 
  return {
    confirm,
    onConfirm,
    onCancel,
    confirmState: state,
    resetConfirmState: resetState
  }
}

Add Modal.Confirm Component

containers/Modal/Confirm/index.tsx
import type { FC } from 'react'
import { Modal } from 'containers'
import { useConfirm } from 'services'
 
interface Props {}
 
const ConfirmModal: FC<Props> = () => {
  const { onConfirm, onCancel, content, confirmState, resetConfirmState } =
    useConfirm()
  if (!confirmState.isOpen) return null
  return (
    <Modal
      isOpen={confirmState.isOpen}
      onClose={resetConfirmState}
      maxWidth="max-w-sm"
    >
      <div className="p-4">
        <div>{content}</div>
        <div className="flex justify-between">
          <button onClick={onCancel}>아니오</button>
          <button onClick={onConfirm}>예</button>
        </div>
      </div>
    </Modal>
  )
}
 
export default ConfirmModal
containers/Modal/index.tsx
import ConfirmModal from './Confirm'
 
export default Object.assign(Modal, { Confirm: ConfirmModal })

Add Component Globally

page/_app.tsx
import type { AppProps } from 'next/app'
import { Modal } from 'containers'
 
interface Props {}
interface State {}
 
function MyApp({ Component, pageProps }: AppProps<Props>) {
  return (
    <>
      <Component {...pageProps} />
      <Modal.Confirm />
    </>
  )
}
 
export default MyApp

Usage

import { useConfirm } from 'services'
 
const Page = () => {
  const { confirm } = useConfirm()
 
  const handleConfirm = async () => {
    const isConfirmed = await confirm('작성을 중단하시겠습니까?')
    console.log('isConfirmed', isConfirmed)
  }
 
  return (
    <div>
      <button onClick={handleConfirm}>Confirm</button>
    </div>
  )
}

© 2023 kidow. All rights reserved.
안녕하세요?