useConfirm
window.confirm
시 뜨는 모달을 직접 커스텀해서 유사하게 구현한 hooks입니다.
Prerequisite
- npm
- Yarn
npm install recoil
yarn add recoil
services/store/index.ts
import type { ReactNode } from 'react'
import { atom, useRecoilState, useResetRecoilState } from 'recoil'
const confirmState = atom<{ content: ReactNode; isOpen: boolean }>({
key: 'confirmState',
default: {
content: '',
isOpen: false
}
})
services/hooks/index.tsx
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, reject) => {
confirmCb = resolve
})
}
return {
confirm,
onConfirm,
onCancel,
confirmState: state,
resetConfirmState: resetState
}
}
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
Settings
containers/Modal/index.tsx
...
import type { FC } from 'react'
import ConfirmModal from './Confirm'
interface Props {}
interface IModal extends FC<Props> {
Confirm: typeof ConfirmModal
}
const Modal: IModal = () => {
return ...
}
Modal.Confirm = ConfirmModal
export default Modal
Next.js
pages/_app.tsx
import App from 'next/app'
import { Modal } from 'containers'
class MyApp extends App {
render() {
const { Component, pageProps } = this.props
return (
<>
<Component {...pageProps} />
<Modal.Confirm />
</>
)
}
}
export default MyApp
React
src/App.tsx
import { ConfirmModal } from 'containers'
const App = () => {
return (
<>
<div>Create React App</div>
<ConfirmModal />
</>
)
}
export default App
Usage
import { useConfirm } from 'services'
const Page = () => {
const { confirm } = useConfirm()
const handleConfirm = async () => {
try {
const isConfirmed = await confirm('작성을 중단하시겠습니까?')
console.log('isConfirmed', isConfirmed)
} catch (err) {
console.log(err)
}
}
return (
<div>
<button onClick={handleConfirm}>Confirm</button>
</div>
)
}