在React项目的开发过程中,很多时候像Toast 、Confirm 、Notification 、Drawer等等组件我们预期的是非必要可以不需要 ,只有在使用的时候才需要渲染。像window.confirm 一样的操作。 虽然很多React的组件库都实现了,比如Antd 的Modal 组件实现了Modal.confirm等。
但是平时我们不想引入组件库只想通过Tailwindcss或者原生的css写的时候就可以通过React-Call这个组件库就可以实现对应的功能:官网
创建Confirm组件
Confirm.tsx
import { createCallable } from 'react-call'
interface Props {
message: string
}
type Response = boolean
export const Confirm = createCallable<Props, Response>(({ call, message }) => (
<div
role="dialog"
aria-modal="true"
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm"
>
<div className="w-full max-w-sm rounded-lg border border-[var(--color-border)] bg-[var(--color-bg)] p-6 shadow-2xl">
<p className="text-base text-[var(--color-fg)]">{message}</p>
<div className="mt-6 flex items-center justify-end gap-3">
<button
type="button"
onClick={() => call.end(false)}
className="rounded-md border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-fg-muted)] transition-colors hover:text-[var(--color-fg)]" >
取消
</button>
<button
type="button"
onClick={() => call.end(true)}
className="rounded-md bg-[var(--color-accent)] px-4 py-2 text-sm font-medium text-[var(--color-accent-fg)] transition-colors hover:bg-[var(--color-accent-hover)]"
>
继续
</button>
</div>
</div>
</div>
))
Confirm.displayName = 'Confirm'
将组件引入到root中
js
import { Confirm } from './Confirm'
import { DeleteButton } from './DeleteButton'
export default function App() {
return (
<>
<Confirm />
<DeleteButton />
</>
)
}
在项目的任何地方引用创建的Comfirm组件
js
import { useState } from 'react'
import { Confirm } from './Confirm'
export const DeleteButton = () => {
const [status, setStatus] = useState<'idle' | 'deleted' | 'cancelled'>('idle')
const handleClick = async () => {
const accepted = await Confirm.call({
message: '确定要删除这条数据?',
})
setStatus(accepted ? 'deleted' : 'cancelled')
}
return (
<div className="flex flex-col items-center gap-3">
<button
type="button"
onClick={handleClick}
className="rounded-md bg-red-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-red-700"
>
删除
</button>
<span className="font-mono text-xs text-[var(--color-fg-subtle)]">
{status === 'idle' && '→ awaiting click...'}
{status === 'deleted' && (
<span className="text-[var(--color-accent)]">→ deleted</span>
)}
{status === 'cancelled' && '→ cancelled'}
</span>
</div>
)
}