今回解説するのは下記の通りです。
- ライブラリを使ってテーブルデータを表示する
- 行内のボタンをクリックし、編集用のモーダルを開く
なお、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からお願いします。