0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Reactの勉強③ ポップアップ

Last updated at Posted at 2025-05-15

今回の狙い
前回の内容で表示させていたポップアップ画面が寂しい。。。

という事で、ポップアップ画面を作ってみたいと思います。
具体的な目標として、以下のポップアップを、
image.png
以下のポップアップ画面に変える事を目標とします。
image.png

Reactのプログラム
以下のプログラムを用意します。

フォルダ構成
└── src
    ├── index.js   (初期起動プログラム)
    └── App.js    (画面へ表示される本体)
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
app.js
import { useState } from 'react';
import { Grid, Select, MenuItem, InputLabel, TextField, Button, Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
import { styled } from '@mui/material/styles';

// 正常の時のダイアログの見出しスタイル
const SuccessDialogTitle = styled(DialogTitle)(({ theme }) => ({
  backgroundColor: theme.palette.primary.main,
  color: theme.palette.primary.contrastText,
}));

// エラーの時のダイアログの見出しスタイル
const ErrorDialogTitle = styled(DialogTitle)(({ theme }) => ({
  backgroundColor: theme.palette.error.main,
  color: theme.palette.error.contrastText,
}));

export default function App() {

// 初期値設定
  const [showDialog, setShowDialog] = useState(false);
  const [form, setForm] = useState({ mode: 'CMPL', msg: '正常を選択しています' });
  const [dialogMessage, setDialogMessage] = useState('');
  const [isSuccess, setIsSuccess] = useState(false);

// 変更された入力値を適用する処理
  const handleForm = (e) => {
    setForm({
      ...form,
      [e.target.name]: e.target.value,
    });
  };

  // ポップアップ画面の起動処理
  const handleOpenDialog = (message, success) => {
    setDialogMessage(message);
    setIsSuccess(success);
    setShowDialog(true);
  };

  // ポップアップ画面の終了処理
  const handleCloseDialog = () => {
    setShowDialog(false);
  };

  // 実行ボタン処理
  const onsubmit = () => {
    console.log(`a:${form.mode}`);
    if (form.mode === "ER") {
      handleOpenDialog(form.msg, false);
    } else {
      handleOpenDialog(form.msg, true);
    }
  };

// 画面定義
  return (
    <div className="App">
      <form>
        <Grid container spacing={2}>
          <Grid size={{xs:12}}>
              <InputLabel id="mode">モード選択</InputLabel>
              <Select labelid="mode" name="mode" value={form.mode} onChange={handleForm}>
                <MenuItem value="ER">エラー</MenuItem>
                <MenuItem value="CMPL">正常</MenuItem>
              </Select>
          </Grid>
          <Grid size={{xs:12}}>
            <TextField id="msg" name="msg" label="ポップアップメッセージ" value={form.msg} onChange={handleForm} />
          </Grid>
          <Grid size={{xs:12}}>
            <Button variant="contained" color="primary" onClick={onsubmit}>実行</Button>
          </Grid>
        </Grid>
      </form>

      <Dialog open={showDialog} onClose={handleCloseDialog}>
        {isSuccess ? (
          <SuccessDialogTitle>Infomation</SuccessDialogTitle>
        ) : (
          <ErrorDialogTitle>Error</ErrorDialogTitle>
        )}
        <DialogContent>
          <p>{dialogMessage}</p>
        </DialogContent>
        <DialogActions>
          <Button onClick={handleCloseDialog} color="primary">
            閉じる
          </Button>
        </DialogActions>
      </Dialog>
    </div>
  );
}

実行すると、以下の画面が起動し、
image.png

「実行」ボタンでポップアップ画面が表示されます。
image.png

可読性を考える
ある程度、動作が確立したら、少しメンテナンスも考えて可読性を上げたい。
では、どのように改造して可読性を向上させるか? ここで少し問題が…
 <可読性> ・・・ プログラムを見易く、解り易くがする事
そこで、Aiに可読性の良いプログラムを提案させると、

実行ボタン処理.js
  const onsubmit = () => {
    console.log(`a:${form.mode}`);
    if (form.mode === "ER") {
      handleOpenDialog(form.msg, false);
    } else {
      handleOpenDialog(form.msg, true);
    }
  };

この部分が、以下のように変わります。

実行ボタン処理.js
  const onsubmit = () => {
    console.log(`a:${form.mode}`);
    handleOpenDialog(form.msg, form.mode !== "ER");
  };

確かに、スマートになって見易くなった…と。ただ、「可読性」を考えると…??
私のようなジジィ世代は、if文があった方が見易い(可読性が高い)となる訳です。

と、、、諸説ありますが(ほんとに多い…)、このままですと、少々メンテナンス性が低いので、ジジィ的な可読性の向上を目指します。

フォルダ構成
└── src /
    ├── components /
    |    ├── Form.js
    |    └── AlertDialog.js
    ├── pages /
    |    └── App.js
    └── index.js
Form.js
import React from 'react';
import { Grid, Select, MenuItem, InputLabel, TextField, Button } from '@mui/material';

export default function Form({ form, handleForm, onsubmit }) {
  return (
    <form>
      <Grid container spacing={2}>
        <Grid size={{xs:12}}>
          <InputLabel id="mode">モード選択</InputLabel>
          <Select labelid="mode" name="mode" value={form.mode} onChange={handleForm}>
            <MenuItem value="ER">エラー</MenuItem>
            <MenuItem value="CMPL">正常</MenuItem>
          </Select>
        </Grid>
        <Grid size={{xs:12}}>
          <TextField id="msg" name="msg" label="ポップアップメッセージ" value={form.msg} onChange={handleForm} />
        </Grid>
        <Grid size={{xs:12}}>
          <Button variant="contained" color="primary" onClick={onsubmit}>実行</Button>
        </Grid>
      </Grid>
    </form>
  );
}
AlertDialog.js
import React from 'react';
import { Button, Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
import { styled } from '@mui/material/styles';

// 正常の時のダイアログの見出しスタイル
const SuccessDialogTitle = styled(DialogTitle)(({ theme }) => ({
  backgroundColor: theme.palette.primary.main,
  color: theme.palette.primary.contrastText,
}));

// エラーの時のダイアログの見出しスタイル
const ErrorDialogTitle = styled(DialogTitle)(({ theme }) => ({
  backgroundColor: theme.palette.error.main,
  color: theme.palette.error.contrastText,
}));

// ダイアログの処理(オープン処理、クローズ処理、メッセージ、エラー判定)
export default function AlertDialog({ open, onClose, message, isSuccess }) {
  return (
    <Dialog open={open} onClose={onClose}>
      {isSuccess ? (
        <SuccessDialogTitle>Infomation</SuccessDialogTitle>
      ) : (
        <ErrorDialogTitle>Error</ErrorDialogTitle>
      )}
      <DialogContent>
        <p>{message}</p>
      </DialogContent>
      <DialogActions>
        <Button onClick={onClose} color="primary">
          閉じる
        </Button>
      </DialogActions>
    </Dialog>
  );
}
App.js
import React, { useState } from 'react';
import Form from '../components/Form';
import AlertDialog from '../components/AlertDialog';

export default function App() {
  const [showDialog, setShowDialog] = useState(false);
  const [form, setForm] = useState({ mode: 'CMPL', msg: '正常を選択しています' });
  const [dialogMessage, setDialogMessage] = useState('');
  const [isSuccess, setIsSuccess] = useState(false);

  // 変更された入力値を適用する処理
  const handleForm = (e) => {
    setForm({
      ...form,
      [e.target.name]: e.target.value,
    });
  };

  // ポップアップ画面の起動処理
  const handleOpenDialog = (message, success) => {
    setDialogMessage(message);
    setIsSuccess(success);
    setShowDialog(true);
  };

  // ポップアップ画面の終了処理
  const handleCloseDialog = () => {
    setShowDialog(false);
  };

  // 実行ボタン処理
  const onsubmit = () => {
    console.log(`a:${form.mode}`);
    handleOpenDialog(form.msg, form.mode !== "ER");
  };

  // 画面定義
  return (
    <div className="App">
      <Form form={form} handleForm={handleForm} onsubmit={onsubmit} />
      <AlertDialog open={showDialog} onClose={handleCloseDialog} message={dialogMessage} isSuccess={isSuccess} />
    </div>
  );
}
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './pages/App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

フォームを2つに分けて、イベントも切り出して、かなりスッキリした感じです。

以上、御疲れ様でした~。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?