💡

【React】1つのページで複数のモーダルを実装する

2 min read

はじめに

下記のように複数のボタンが存在して、そのボタンごとに異なるモーダルを表示する方法の紹介です。
愚直にやろうとして意外とハマったので記録しておきます。

modals

コード

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

ログインするとコメントできます