OKボタンや、YES / NO のボタンでユーザーに確認を促すメッセージダイアログを出すシーンは多くあり、その度に個別にダイアログを実装するのは無駄である。
そこで、汎用的に使えるダイアログコンポーネントを作ってみた。
スポンサーリンク
完成イメージ
作成するコンポーネントの完成イメージは次のとおり。よくあるメッセージダイアログで、使い方の説明は不要であろう。
今回は、OKまたは、YES / NOの2種類のボタンを表示できるように、プロパティで切り替えられるようにする。
スポンサーリンク
実装
まずは、ダイアログ側のソースである。
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle
} from '@mui/material';
import PropTypes from 'prop-types';
import React, { useEffect, useState } from 'react';
function CommonDialog(props: any) {
// プロパティの受け取り
const {
title,
message,
onAccept,
onClose,
open,
buttonType
} = props;
const [dialogOpen, setDialogOpen] = useState(false);
// 承諾(OK または YES ボタンをクリック)した時
const handleAccept = () => {
handleClose();
onAccept();
};
// ダイアログクローズ
const handleClose = () => {
setDialogOpen(false);
onClose();
};
// openの値が変化した時
useEffect(() => setDialogOpen(open), [open]);
return (
<Dialog
open={dialogOpen}>
<DialogTitle>
<span>{title}</span>
</DialogTitle>
<DialogContent >
<Box>
{message}
</Box>
</DialogContent>
<DialogActions>
{buttonType == ButtonType.OkOnly &&
<Button onClick={handleAccept}>OK</Button>
}
{buttonType == ButtonType.YesNo &&
<>
<Button onClick={handleAccept}>はい</Button>
<Button onClick={handleClose}>いいえ</Button>
</>
}
</DialogActions>
</Dialog>
);
}
// ボタン種別
export enum ButtonType {
OkOnly = "OkOnly",
YesNo = "YesNo",
}
// プロパティ
CommonDialog.propTypes = {
title: PropTypes.string.isRequired,
message: PropTypes.string.isRequired,
onAccept: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
open: PropTypes.bool.isRequired,
buttonType: PropTypes.oneOf([ButtonType.OkOnly, ButtonType.YesNo]).isRequired
};
export default CommonDialog;
次にダイアログを呼び出す側のコンポーネントを実装する。
import Button from '@mui/material/Button';
import React, { useState } from 'react';
import CommonDialog, { ButtonType } from './dialog/CommonDialog';
function Sample() {
// ダイアログ用のstate
const [digOpen, setDigOpen] = useState(false);
return (
<div>
<CommonDialog
title="タイトル"
message="メッセージ本文です。"
buttonType={ButtonType.OkOnly}
open={digOpen}
onAccept={() => console.log("onAccept")}
onClose={() => setDigOpen(false)}
/>
<Button onClick={() => setDigOpen(true)}>
OPEN
</Button>
</div>
);
}
export default Sample;
スポンサーリンク
実装2(スマホ時はフルスクリーンで表示)
スマホなどの、画面サイズが小さいデバイスの場合、フルスクリーンでダイアログを表示するように改造したソースは以下である。
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
useMediaQuery } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import PropTypes from 'prop-types';
import React, { useEffect, useState } from 'react';
function CommonDialog(props: any) {
// プロパティの受け取り
const {
title,
message,
onAccept,
onClose,
open,
buttonType
} = props;
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
const [dialogOpen, setDialogOpen] = useState(false);
// 承諾(OK または YES ボタンをクリック)した時
const handleAccept = () => {
handleClose();
onAccept();
};
// ダイアログクローズ
const handleClose = () => {
setDialogOpen(false);
onClose();
};
// openの値が変化した時
useEffect(() => setDialogOpen(open), [open]);
return (
<Dialog
open={dialogOpen}
maxWidth="sm"
fullScreen={fullScreen}>
<DialogTitle>
<span>{title}</span>
</DialogTitle>
<DialogContent >
<Box>
{message}
</Box>
</DialogContent>
<DialogActions>
{buttonType == ButtonType.OkOnly &&
<Button variant="contained" onClick={handleAccept}>OK</Button>
}
{buttonType == ButtonType.YesNo &&
<>
<Button variant="contained" onClick={handleAccept}>はい</Button>
<Button color="secondary" variant="outlined" onClick={handleClose}>いいえ</Button>
</>
}
</DialogActions>
</Dialog>
);
}
// ボタン種別
export enum ButtonType {
OkOnly = "OkOnly",
YesNo = "YesNo",
}
// プロパティ
CommonDialog.propTypes = {
title: PropTypes.string.isRequired,
message: PropTypes.string.isRequired,
onAccept: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
open: PropTypes.bool.isRequired,
buttonType: PropTypes.oneOf([ButtonType.OkOnly, ButtonType.YesNo]).isRequired
};
export default CommonDialog;
上のコードのポインタは、useMediaQuery
で画面の横幅が 500px
を下回った場合、Dialog
コンポーネントの fullScreen
プロパティに true
を設定している部分である。
0 件のコメント:
コメントを投稿