💡
【React】1つのページで複数のモーダルを実装する
はじめに
下記のように複数のボタンが存在して、そのボタンごとに異なるモーダルを表示する方法の紹介です。
愚直にやろうとして意外とハマったので記録しておきます。
コード
CSSフレームワークにChakra UIを使っていますが、実装ロジックはどのフレームワークを使っても変わらないと思います。
import { useState } from 'react'
import {
Box,
Flex,
HStack,
Button,
AlertDialog,
AlertDialogOverlay,
AlertDialogContent,
AlertDialogBody,
} from '@chakra-ui/react'
export default function Modal() {
const [selectedItem, setSelectedItem] = useState<string>('')
const ButtonList = ['Button1', 'Button2', 'Button3', 'Button4', 'Button5']
const onOpenDialog = (name: string) => {
setSelectedItem(name)
}
const onCloseDialog = () => {
setSelectedItem('')
}
return (
<Flex w="100vw" h="100vh" justifyContent="center">
<HStack>
{ButtonList.map((item) => {
return (
<Box key={item}>
<Button onClick={() => onOpenDialog(item)}>{item}</Button>
<AlertDialog
isOpen={item === selectedItem}
onClose={onCloseDialog}
leastDestructiveRef={undefined}
autoFocus={false}
isCentered
>
<AlertDialogOverlay>
<AlertDialogContent>
<AlertDialogBody>{item}</AlertDialogBody>
</AlertDialogContent>
</AlertDialogOverlay>
</AlertDialog>
</Box>
)
})}
</HStack>
</Flex>
)
}
ポイント
この部分でクリックされたボタンの情報を保持するようにします。
const [selectedItem, setSelectedItem] = useState<string>('')
// 省略
const onOpenDialog = (name: string) => {
setSelectedItem(name)
}
const onCloseDialog = () => {
setSelectedItem('')
}
ボタンと同じ数だけModalを用意して、押下されたボタンに対応するModalだけ表示するようにします。
<AlertDialog
isOpen={item === selectedItem} // 押下されたボタンと一致するModalのみ表示
onClose={onCloseDialog}
leastDestructiveRef={undefined}
autoFocus={false}
isCentered
>
<AlertDialogOverlay>
<AlertDialogContent>
<AlertDialogBody>{item}</AlertDialogBody>
</AlertDialogContent>
</AlertDialogOverlay>
</AlertDialog>
おわり
実装できてしまえば何のことはないシンプルなコードですが、思いつくまで結構時間がかかってしまいました。
何かの参考になれば幸いです。
Discussion