buto > /dev/null

だいたい急に挑戦してゴールにたどり着かずに飽きる日々です

react typeで型定義して使い回す

typeでオブジェクト型を定義する

typescriptではtypeキーワードで作成したオブジェクトを型として扱うことができます

「key: プリミティブ型」の書き方で定義していきます

type Item = {
  id: number,
  category: string,
  item: string,
  price: number
};

APIのレスポンスをtypeで型定義しておくと型チェックがされるのでケアレスミスが防げそう!

typeインポート&エクスポート

定義した型はエクスポートすると他のtsxファイル(別コンポーネント)でもインポートして使うことができます

export type {Item};
import type {Item} from '../logic/useItem';

アプリで使うtype一覧をNameSpaceを使って1つのファイルに定義しているプロジェクトも見たのですが、

「NS.Item」のようにNameSpaceを指定する必要があるのと(ちなみにそのプロジェクトではNameSpacehaNSしかなかった)

型一覧を1ファイルにまとめてしまうことで1つ1つの型がどんな画面、処理で使われているか分かりにくく感じました

なので型定義は型を使うロジック関数のファイルに定義しています

typeを使ってテーブルにデータを表示

Material-UIのTableに商品のデータを表示します

components/DataTable.tsx

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
  };

  useEffect(() => {
    setItemList([sample]);
    regularItem();
    setSaleItem(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>
              <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で定義した「Item型」の配列データを表示します

App.tsx

import Box from '@mui/material/Box';
import Header from './components/Header';
import DataTable from './components/DataTable';

function App() {

  return (
    <div>
      <Box
        sx={{
          padding:1,
          margin:1
        }}
      >
        <Header/>
      </Box>
      <Box
        sx={{
          padding:1,
          margin:1
        }}
      >
        <DataTable/>
      </Box>
    </div>
  );
}

export default App;

※Header.tsxはAppBarだけなので割愛します

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};

Item型の定義とstate変数の型指定をしています

Item型のデータが表示されました!(変数sampleで定義したデータが入っていない?) f:id:butorisa:20210922001041p:plain