昨日の記事でMaterial-UIのTableを使ってオブジェクト配列を持つstate変数の値を表示しましたが
最初にsetState()でセットしたオブジェクトが表示されていませんでした
components/DataTable.tsx
useItem.tsxで取得したstate変数をDataTable.tsxで定義したstate変数にセットし直しています
useEffectでログ出力を追加しました
import {useState, useEffect} from 'react'; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import useItem from '../logic/useItem'; // オブジェクト型をインポート import type {Item} from '../logic/useItem'; function DataTable() { const {itemList, setItemList, addItem} = useItem(); const [saleItem, setSaleItem] = useState<Item[]>([]); const sample: Item = { id: 0, category: 'none', item: 'sampleItem', price: 0 }; let array: Item[] = []; array.push(sample); useEffect(() => { setItemList(array); console.log('useEffect([])'); console.log('itemList : ' + JSON.stringify(itemList)); console.log('**************'); // regularItem(); }, []); useEffect(() => { setSaleItem(itemList); console.log('useEffect([itemList])'); console.log('itemList : ' + JSON.stringify(itemList)); console.log('saleItem' + JSON.stringify(saleItem)); console.log('**************'); }, [itemList]); const regularItem = () => { addItem('sweets', 'chocolate', 250); addItem('sweets', 'muffin', 390); addItem('snack', 'potato chips', 180); addItem('beverage', 'cola', 120); }; return ( <TableContainer> <Table sx={{ maxWidth: 250 }}> <TableHead> <TableRow> <TableCell>id</TableCell> <TableCell>category</TableCell> <TableCell>item</TableCell> <TableCell>price(¥)</TableCell> </TableRow> </TableHead> <TableBody> {saleItem.map(item => ( <TableRow key={item.id}> <TableCell align="right">{item.id}</TableCell> <TableCell>{item.category}</TableCell> <TableCell>{item.item}</TableCell> <TableCell align="right">{item.price}</TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> ); } export default DataTable;
logic/useItem.tsx ※昨日と同じです
import {useState} from 'react'; function useItem() { const [itemList, setItemList] = useState<Item[]>([]); const addItem = (category:string, item:string, price:number) => { const el:Item = { id: itemList.length, category: category, item: item, price: Math.ceil(price * 1.1) }; const current = itemList; current.push(el); setItemList(current); }; return {itemList, setItemList, addItem}; }; export default useItem; /* 商品のオブジェクト型 */ type Item = { id: number, category: string, item: string, price: number }; export type {Item};
初期表示で変数sampleの値が表示されています
ログを読み解くと、、、
- 第2引数が
[]
のuseEffect()が実行され、useItem.tsxのitemListに値がセットされる - この時点でのitemListは値がセットされる前の状態なので
[]
- 第2引数が[itemList]のuseEffect()が実行される
- saleItemはもちろん
[]
- itemListが変更されたので第2引数が[itemList]のuseEffect()が実行される
- DataTable.tsxのsaleItemに値がセットされる
- itemListは値がセットされた後の状態になっている
- この時点でのsaleItemは値がセットされる前の状態なので
[]
state変数の変更反映はレンダリング後なのでstate変数を他の変数に代入し直して表示させる必要があります