🔄
react-callで実装する確認モーダル
はじめに
Webアプリケーションにおいて、ユーザーが重要な操作(データ削除など)を行う前に確認を取るケースがあります。この確認フローをモーダル等を使って実装すると、モーダルの開閉状態をstateで管理する必要があったりと実装が複雑になりがちです。
今回は、react-callを活用することで、確認モーダルの実装を簡潔に行う方法を紹介します。
react-callとは
react-callは、Reactコンポーネントを手続き的に処理できるようにするライブラリです。
react-callに関してはこちらの記事が参考になります。
実装例:削除確認モーダル
1. 確認モーダルコンポーネントの作成
まず、確認モーダルコンポーネントを作成します。
今回はshadcn/uiを使って実装を行っています。
react-call-modal.tsx
'use client'
import { createCallable } from 'react-call'
import { Button } from './ui/button'
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from './ui/dialog'
interface Props { message: string }
type Response = boolean
export const { Root, ...Confirm } = createCallable<Props, Response>(({ call, message }) => (
<Dialog defaultOpen>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>削除モーダル</DialogTitle>
<DialogDescription>
{message}
</DialogDescription>
</DialogHeader>
<DialogFooter className="flex items-center">
<Button variant="outline" onClick={() => call.end(false)}>
キャンセル
</Button>
<Button variant="destructive" onClick={() => call.end(true)}>
削除
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
))
このコンポーネントは以下の通りです
-
createCallable
を使用して呼び出し可能なコンポーネントを作成 - モーダル内のボタンクリック時に
call.end()
で結果を返す
2. Rootコンポーネントをレイアウトへ配置
確認モーダルを使用するために、アプリケーションのルートレイアウトにRootコンポーネントを配置します。
layout.tsx
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="ja">
<body>
{children}
<Root />
</body>
</html>
)
}
3. 確認モーダルの実際の使用例
Confirm.call()
の結果に基づいて削除処理を実行するか判定します
// 省略
<DropdownMenuItem onClick={async () => {
const confirmed = await Confirm.call({ message: '本当に削除しますか?' })
if (confirmed) {
remove.mutate({ id })
}
}}>
<TrashIcon className="mr-2 size-4" />
削除
</DropdownMenuItem>
// 省略
まとめ
react-callを使うことでモーダルの実装や、モーダル内の操作結果による処理の分岐などを簡潔に行うことができます。この他にも通知やトーストの表示等にも活用できるため、これらを実装する際はぜひreact-callの採用を検討してみてください。

ちょっと株式会社(chot-inc.com)のエンジニアブログです。 フロントエンドエンジニア募集中! カジュアル面接申し込みはこちらから chot-inc.com/recruit/iuj62owig
Discussion
ニュアンス Promise でいうところの withResolvers() 的な感じか……?
react-callのコードを見たところ、callの中でPromiseを生成しており、
外部からcall.end()を呼ぶことでPromiseを解決しているため、「withResolvers() 的な感じ」と言えそうだと思いました…!