Rio Blog

世界のどこかでゆるく生きるITエンジニアのブログ

react-data-table-componentで管理画面をつくる

今回解説するのは下記の通りです。

  1. ライブラリを使ってテーブルデータを表示する
  2. 行内のボタンをクリックし、編集用のモーダルを開く

なお、UIにはMaterial UIを利用します。

インストール

まずはreact-data-table-componentをインストールします。

npm

npm install react-data-table-component

yarn

yarn add react-data-table-componen

サンプルや詳細な使い方はこちらから
https://react-data-table-component.netlify.app/

データの表示

まずはサンプルとなるデータテーブルを作って表示させます(実際にはMySQL等のデータベースから取得するのが一般的かと思いますが、今回は割愛します)。

import { useState } from 'react';
import { Box, Button, Switch } from '@mui/material';
import DataTable from 'react-data-table-component';

export default function App() {
  const [isOpen, setIsOpen] = useState(false)
  const [rowData, setRowData] = useState({name:"", number:0, active:false})

  const columns = [
    {
      name: 'Name',
      selector: (row: { name: string; }) => row.name,
    },
    {
      name: 'Number',
      selector: (row: { number: number; }) => row.number,
    },
    {
      name: 'Active',
      cell: (row: { active: boolean }) => (
        <Switch
          defaultChecked={row.active}
          disabled
        />
      )
    },
    {
      name: 'Edit',
      button: true,
      cell: (row: { name: string; number: number; active: boolean; }) => (
        <Button
          variant="contained"
          size="small"
          color="primary"
        >
          Edit
        </Button>
      )
    },
  ];

  const data = [
    {
      id: 1,
      name: 'John',
      number: 101,
      active: true,
    },
    {
      id: 2,
      name: 'Mary',
      number: 102,
      active: false,
    },
  ]

  return (
    <Box mt={3} ml={24} mr={24}>
      <DataTable
        columns={columns}
        data={data}
        striped={true}
      />
    </Box>
  )
}

これで下記のように行内にトグルスイッチとボタンを含むテーブルを作成できました。まだEditボタンをクリックしても何も起きませんので、モーダルを開く処理を追加していきます。

モーダルを開き、データを表示する

Editボタンをクリックすると、行データを取得しつつ、モーダルを開くようにします。

// App.tsx
import { useState } from 'react';
import { Box, Button, Switch } from '@mui/material';
import { SampleModal } from './SampleModal';
import DataTable from 'react-data-table-component';

export default function App() {
  const [isOpen, setIsOpen] = useState(false)
  const [rowData, setRowData] = useState({name:"", number:0, active:false})

  const editRow = (row: { name: string; number: number; active: boolean; }) => {
    const rowData = {
      name: row.name,
      number: row.number,
      active: row.active
    }
    setRowData(rowData)
    setIsOpen(true)
  }

  const columns = [
    {
      name: 'Name',
      selector: (row: { name: string; }) => row.name,
    },
    {
      name: 'Number',
      selector: (row: { number: number; }) => row.number,
    },
    {
      name: 'Active',
      cell: (row: { active: boolean }) => (
        <Switch
          defaultChecked={row.active}
          disabled
        />
      )
    },
    {
      name: 'Edit',
      button: true,
      cell: (row: { name: string; number: number; active: boolean; }) => (
        <Button
          variant="contained"
          size="small"
          color="primary"
          onClick={() =>
            editRow(row)
          }
        >
          Edit
        </Button>
      )
    },
  ];

  const data = [
    {
      id: 1,
      name: 'John',
      number: 101,
      active: true,
    },
    {
      id: 2,
      name: 'Mary',
      number: 102,
      active: false,
    },
  ]

  return (
    <Box mt={3} ml={24} mr={24}>
      <DataTable
        columns={columns}
        data={data}
        striped={true}
      />
      <SampleModal
        isOpen={isOpen}
        setIsOpen={setIsOpen}
        rowData={rowData}
      />
    </Box>
  )
}

モーダルは別コンポーネントにし、propsで行データを渡します。

//SampleModal.tsx
import Modal from 'react-modal';
import { Button, Grid, Switch, TextField, Typography } from '@mui/material';

export const SampleModal = (props: {
    setIsOpen: (arg0: boolean) => void; isOpen: boolean; rowData: { name: string; number: number; active: boolean | undefined; }; }) => {
    const modalStyle = {
        content: {
            top: '200px',
            left: '400px',
            right: '400px',
            bottom: '240px',
        }
    }

    const modalIsClose = () => {
        props.setIsOpen(false)
    }

    return (
        < Modal
            isOpen={props.isOpen}
            style={modalStyle}
        >
            <Grid container direction="column" spacing={1}>
                <Grid item>
                    <Typography>Name</Typography>
                    <TextField
                        id="department_name"
                        variant="outlined"
                        type="text"
                        defaultValue={props.rowData.name}
                    />
                </Grid>
                <Grid item>
                    <Typography>Number</Typography>
                    <TextField
                        id="department_name"
                        variant="outlined"
                        type="text"
                        defaultValue={props.rowData.number}
                    />
                </Grid>
                <Grid item>
                        <Typography>Active</Typography>
                        <Switch
                            defaultChecked={props.rowData.active}
                            color="primary"
                        />
                    </Grid>
            </Grid>
            <Grid container justifyContent="flex-end" spacing={1}>
                <Grid item>
                    <Button
                        variant="outlined"
                        onClick={modalIsClose}
                    >
                        Close
                    </Button>
                </Grid>
                <Grid item>
                    <Button
                        variant="contained"
                    >
                        Save
                    </Button>
                </Grid>
            </Grid>
        </Modal>
    )
}

下記のようにモーダルが開き、取得した値が表示できました。

今回は以上となります。

何か質問等があれば、コメント欄やTwitterのDMからお願いします。