Alert と Snackbar を組み合わせたメッセージの表示コンポーネントの紹介
javascript
typescript
mui
react
投稿日: 2024/06/26
フォームの保存時などエラーや成功のメッセージを表示したいと思います。
こんな感じです。
このコンポーネントを使いやすいようにまとめたのでよければご使用ください。
AlertSnackbarコンポーネントの紹介
AlertSnackbarコンポーネントは以下のようになります。
AlertSnackbar.tsx
import { FC, SyntheticEvent } from "react" import Stack from "@mui/material/Stack" import Snackbar from "@mui/material/Snackbar" import Alert, { AlertColor } from "@mui/material/Alert" import IconButton from "@mui/material/IconButton" import CloseIcon from "@mui/icons-material/Close" export type AlertSnackbarState = { open: boolean body: string severity?: AlertColor } type Props = { alertSnackbarState: AlertSnackbarState setAlertSnackbarState: (state: AlertSnackbarState) => void } export const AlertSnackbar: FC<Props> = (props) => { const handleClose = (event: SyntheticEvent | Event, reason?: string) => { if (reason === "clickaway") { return } props.setAlertSnackbarState({ ...props.alertSnackbarState, body: "", open: false, }) } return ( <Stack spacing={2} sx={{ width: "100%" }}> <Snackbar open={props.alertSnackbarState.open} autoHideDuration={6000} onClose={handleClose} > <Alert variant="filled" severity={props.alertSnackbarState.severity} action={ <IconButton aria-label="close" color="inherit" size="small" onClick={handleClose} > <CloseIcon fontSize="inherit" /> </IconButton> } sx={{ mb: 2 }} > {props.alertSnackbarState.body} </Alert> </Snackbar> </Stack> ) }
ポイントとしてはhandleClose
のsetAlertSnackbarState
でseverity
を更新していないことです。
Snackbarを閉じるときにseverity
を変更すると、一瞬異なる色が見えてちらついてしまいます。
同じ理由でbody
も更新しない方が良いのですが、間違ったメッセージを表示することが無いように消してます。
AlertSnackbarコンポーネントの使い方
AlertSnackbarState型のStateを作成して、これを更新することでメッセージの表示を制御します。
import { FC, useState } from "react" import { AlertSnackbar, AlertSnackbarState, } from "@/components/sharedComponents/AlertSnackbar/AlertSnackbar" export const ProfileForm: FC = () => { const [alertSnackbarState, setAlertSnackbarState] = useState<AlertSnackbarState>({ body: "", severity: undefined, open: false, }) const onSubmit = async () => { try { // Save or update process setAlertSnackbarState({ open: true, body: "更新しました", }) } catch (e) { setAlertSnackbarState({ open: true, body: "更新に失敗しました", severity: "error", }) } } return ( <> <form onSubmit={onSubmit}>{/* Something */}</form> <AlertSnackbar alertSnackbarState={alertSnackbarState} setAlertSnackbarState={setAlertSnackbarState} /> </> ) }
yosi
Noh を作ってるエンジニア。