※当サイトではアフィリエイト広告を利用しています。

react

reactで作る todo アプリ 2/4

この記事では、下図のような ToDo アプリの開発手順について全 4 部構成で詳しく解説しています。React の基礎から応用までを実際のコーディングを通じて学ぶことに焦点を当てています。初心者から中級者向けの内容となっており、ToDo アプリの開発は、実践的な技能の習得とポートフォリオ作成のための具体的な例として最適だと考えています。

この第 2 部では、json-server の導入とレイアウトの定義を行います。

todoapp-demo

想定読者

  • react の初学者から中級者
  • react を触ったことはあるが、なにかポートフォリオ的な物を作りたい人

記事構成

  1. ToDo アプリの概要と開発環境の構築
  2. json-server の導入とレイアウトの定義
  3. ToDo アプリの機能と API リクエストの実装
  4. Firebase による認証機能の実装

初期化時のソースコードの確認

第 1 部で準備した開発環境で実装を行います。まず初めに React でプロジェクトを初期化した際に生成される主要なディレクトリとファイルの説明をします。

.
├── .vscode
│   └── settings.json
└── frontend
    ├── .git
    ├── .gitignore
    ├── README.md
    ├── node_modules
    ├── package-lock.json
    ├── package.json
    ├── public
    ├── src
    └── tsconfig.json

 

  • node_modules
    node_modules
    ディレクトリには、プロジェクトで使用されるすべての Node.js モジュール(ライブラリや依存関係)が含まれます。これらは npm install や yarn add コマンドを使用して追加され、package.json に記録されます。通常、開発者が直接触ることはほとんどありません。
  • public
    publicディレクトリには、ウェブサーバーに直接公開されるファイルが含まれます。ここには通常、index.html(アプリケーションの主要な HTML ファイル)、画像、および公開用のアイコンなどが含まれます。
  • src
    src(source の略)ディレクトリは、React アプリケーションの主要なソースコードを含む場所です。基本的にはこの中に機能や UI を実装していくことになります。ここには、一般的に React コンポーネント(Typescript の場合は.ts または.tsx ファイル)、CSS スタイルシート、テストファイル、およびアプリケーションロジックが格納されます。今回は MUI を使用するため、CSS スタイルシートは記述しません。src ディレクトリの中にApp.tsxindex.tsxが格納されてますが、これらについては個別に説明します。今回は test は書きませんので、その他のファイルは触りません。

    • App.tsxアプリケーションのルートコンポーネントです。ここで src ディレクトリに記述した機能や UI を呼び出して使用します。
    • index.tsxアプリケーションのエントリーポイントです。ReactDOM.render メソッドを使用して App コンポーネントを DOM にレンダリングします。
  • package.json
    このファイルはプロジェクトのメタデータ、スクリプト、依存関係を定義します。npm や yarn を使用してプロジェクトを管理する際に中心となるファイルで、ビルド時や scripts の内容を記述する際に使用されます。例えば、今回 json-server を使用しますが、scripts に"json-server": "json-server --watch ./src/db/db.json -p 3001"と追記します。
  • package-lock.json
    package-lock.json ファイルは、プロジェクトの全ての依存関係の正確なバージョンを記録します。npm install を実行すると生成されます。プロジェクトをセットアップするすべての開発者が同じバージョンの依存関係を使用することが保証されるため、「私のマシンでは動くけど他のマシンでは動かない」といった問題を防ぐことができます。
  • tsconfig.json
    tsconfig.json ファイルは、TypeScript コンパイラの設定を定義します。このファイルにより、TypeScript のコンパイルオプションやプロジェクトで使用するファイルを指定できます。今回の開発では使用しません。

todoapp の起動

以下のコマンドを入力して todoapp のサーバーを立ち上げます。

cd frontend 
npm start

localhost:3000 にアクセスすると下図を確認できると思います。

react-init

json-server の導入

最初に、json-server をプロジェクトに導入します。json-server は簡易的なデータベースの役割を果たし、データを保存するためのサーバーとして機能します。ローカル環境でのテストや、小規模なアプリケーション開発に非常に便利なツールです。このプロジェクトでは、db という名前のフォルダを作成し、そこにデータを格納します。このデータは、アプリケーションから取得、変更、または削除することができます。

具体的には、以下のようなデータを JSON 形式で保存します。このデータはブラウザからの操作に応じて、取得、追加、変更、または削除されることになります。

{
  "todos": [
    {
      "id": "c44f7456-d00d-432e-ac83-089384da5c1f",
      "title": "タスク1",
      "description": "",
      "done": true,
      "important": false,
      "date": "2024-01-25",
      "createdAt": "2024-01-23 06:01:41"
    },
    {
      "id": "c7a3deb4-436d-4e1c-8688-0f99fd1d59e9",
      "title": "タスク2",
      "description": "",
      "done": false,
      "important": false,
      "date": "",
      "createdAt": "2024-01-24 06:49:09"
    }
  ]
}
  1. json-server のインストール
    json-server をインストールする前に、frontend ディレクトリに移動してください。以下のコマンドを実行します。-D オプションは、json-server を開発依存関係(プロジェクトの本番環境や最終的な製品には含まれないもの)としてインストールすることを意味します。

    npm install -D json-server
  2. db.json の作成
    src ディレクトリ内に db フォルダを作成し、その中に db.json ファイルを作成します。

    // db.json
    {
      "todos": []
    }
  3. json-server を起動するためのコマンドを追記
    package.json の scripts に json-server を起動するためのコマンドを追記します。以下のように記述してください。

      "scripts": {
        "start": "react-scripts start",
        "build": "react-scripts build",
        "test": "react-scripts test",
        "eject": "react-scripts eject",
        "json-server": "json-server --watch ./src/db/db.json -p 3001"
      },

    "json-server": "json-server --watch ./src/db/db.json -p 3001" というコマンドは、src/db/db.jsonファイルを監視し、ポート 3001 で json-server を起動することを意味します。–watch オプションをつけることで指定した JSON ファイルの変更を監視し、リアルタイムでサーバーに反映することができます。3001 ポートには深い意味はなく、React アプリケーションが通常 3000 ポートで起動するため、単に一つ大きい数字を指定しています。

  4. json-server を起動する
    以下のコマンドを実行し、json-server を起動します。これは先程、scripts 内にjson-serverというものを定義したため、実行できるコマンドになります。

    npm run json-server

     

    起動に成功すると以下のようなログを確認できると思います。停止するにはCTRL-Cを押します。

    JSON Server started on PORT :3001
    Press CTRL-C to stop
    Watching ./src/db/db.json...
    
    ♡( ◡‿◡ )
    
    Index:
    http://localhost:3001/
    
    Static files:
    Serving ./public directory if it exists
    
    Endpoints:
    http://localhost:3001/todos

    今後プロジェクトを起動するためには、json-server も起動しておく必要があります。

レイアウトの定義と適用

次に大元のレイアウトを定義していきます。

  1. MUI のインストール
    frontend ディレクトリに移動してから、以下のコマンドを実行し、MUI をインストールします。

    npm install @mui/material @mui/icons-material @emotion/react @emotion/styled
  2. レイアウトの定義
    次に、src ディレクトリ内に layout フォルダを作成し、その中に AppLayout.tsx というコンポーネントを作成します。

    // AppLayout.tsx
    import { Box } from "@mui/material";
    import React from "react";
    import Sidebar from "./Sidebar";
    import { Outlet } from "react-router-dom";
    
    const AppLayout: React.FC = () => {
      return (
        <Box sx={{ display: "flex" }}>
          <Sidebar />
          <Outlet />
        </Box>
      );
    };
    
    export default AppLayout;

     

    AppLayout.tsx の説明
    AppLayout.tsx では、<Sidebar /> と <Outlet /> の 2 つのコンポーネントが配置されています。Sidebar はカスタムコンポーネントで、後ほど詳しく説明します。<Outlet /> は、親ルートコンポーネントのレイアウトを共有しつつ、子ルートに応じて異なるコンテンツを表示するためのコンポーネントです。これにより、共通のヘッダーやフッター、サイドバーを持つページを簡単に作成できます。つまり、ToDo を一覧表示するコンポーネントや ToDo を追加するコンポーネントを作成する際、この AppLayout で定義された共通のレイアウトが利用されます。

    さらに layout フォルダの中に Sidebar.tsx を作成します。
    import {
      Box,
      Divider,
      List,
      ListItem,
      ListItemButton,
      ListItemIcon,
      ListItemText,
      Toolbar,
    } from "@mui/material";
    import React from "react";
    import StarIcon from "@mui/icons-material/Star";
    import TaskAltIcon from "@mui/icons-material/TaskAlt";
    import AllInclusiveIcon from "@mui/icons-material/AllInclusive";
    import FormatListBulletedIcon from "@mui/icons-material/FormatListBulleted";
    import { useNavigate } from "react-router-dom";
    
    const Sidebar: React.FC = () => {
      const navigate = useNavigate();
      const listItems = [
        {
          text: "Todos",
          icon: <FormatListBulletedIcon />,
          to: "/",
        },
        {
          text: "Important",
          icon: <StarIcon />,
          to: "/important",
        },
        {
          text: "All",
          icon: <AllInclusiveIcon />,
          to: "/all",
        },
        {
          text: "Complited",
          icon: <TaskAltIcon />,
          to: "complited",
        },
      ];
    
      const handleItemClick = (to: string) => {
        navigate(to);
      };
    
      return (
        <Box
          component="nav"
          sx={{
            width: { sm: "280px" },
            height: "100vh",
            borderRight: 1, // 1ピクセルの右境界線を追加
            borderColor: "divider", // デフォルトの境界線色を使用
            bgcolor: "secondary.main",
            color: "secondary.contrastText",
            display: "flex",
            flexDirection: "column",
            justifyContent: "space-between",
          }}
        >
          <Box>
            <Toolbar variant="regular" sx={{ fontSize: "22px" }}>
              ToDo App
            </Toolbar>
            <Divider />
            <List>
              {listItems.map((item, index) => (
                <ListItem key={item.text} disablePadding>
                  <ListItemButton onClick={() => handleItemClick(item.to)}>
                    <ListItemIcon>{item.icon}</ListItemIcon>
                    <ListItemText primary={item.text} />
                  </ListItemButton>
                </ListItem>
              ))}
            </List>
            <Divider />
          </Box>
        </Box>
      );
    };
    
    export default Sidebar;​


    Sidebar.tsx の説明
    Sidebar.tsx はサイドバーの UI を構築するためのコンポーネントです。ここでは listItems という配列を用いて、サイドバーに表示する各項目のテキスト、アイコン、そしてナビゲーション先のパスを定義しています。listItems 配列は map 関数を使って展開され、リストアイテムとして配置されます。各リストアイテムのテキストをクリックすると、定義されたパスに沿って各ページに遷移することができます。

  3. テーマの作成
    src ディレクトリ内に theme フォルダを作成し、その中に index.ts ファイルを作成します。

    // index.ts
    import { createTheme as createMuiTheme } from "@mui/material";
    
    const themeOptions = {
      palette: {
        primary: {
          main: "#52658f",
          light: "#7483A5",
          dark: "#394664",
          contrastText: "#FFFFFF",
        },
        secondary: {
          main: "#f7f5e6",
          light: "#F8F7EB",
          dark: "#ACABA1",
          contrastText: "rgba(0, 0, 0, 0.87)",
        },
        background: {
          default: "#e8e8e8",
        },
      },
    };
    
    export const createTheme = () => {
      return createMuiTheme(themeOptions);
    };​

     

    index.ts の説明

    この index.ts ファイルは、アプリケーションのためのカスタムテーマを作成するために使用されます。MUI の createTheme 関数をインポートし、themeOptions オブジェクトを定義しています。このオブジェクト内で、色のパレット(palette)をカスタマイズし、アプリケーションの主要色と補色を設定しています。

    パレット設定:
    primary と secondary プロパティは、アプリケーションの主要な色と補色を定義します。それぞれの色相には、main、light、dark、contrastText の各色相を設定します。
    background プロパティでは、アプリケーションの背景色を定義しています。
    この設定を利用して、createTheme 関数をエクスポートします。この関数はアプリケーションの他の部分で呼び出され、カスタマイズされたテーマを提供する役割を果たします。これにより、アプリケーション全体で一貫したデザインと色使いを実現できます。この部分を変更することで好みのデザイン色を適用することができます。

  4. レイアウトの適用
    App.tsx を以下に書き換え、先程定義したレイアウトを適用します。
    // App.tsx
    import "./App.css";
    import { Route, BrowserRouter, Routes } from "react-router-dom";
    import AppLayout from "./layout/AppLayout";
    import { CssBaseline, ThemeProvider } from "@mui/material";
    import { createTheme } from "./theme";
    
    function App() {
      const theme = createTheme();
    
      return (
        <div className="App">
          <BrowserRouter>
            <ThemeProvider theme={theme}>
              <CssBaseline />
              <Routes>
                <Route path="/" element={<AppLayout />}></Route>
              </Routes>
            </ThemeProvider>
          </BrowserRouter>
        </div>
      );
    }
    
    export default App;​
ここまでの実装で src ディレクトリは以下のようなフォルダ構成になっていると思います。
.
├── App.css
├── App.test.tsx
├── App.tsx
├── db
│   └── db.json
├── index.css
├── index.tsx
├── layout
│   ├── AppLayout.tsx
│   └── Sidebar.tsx
├── logo.svg
├── react-app-env.d.ts
├── reportWebVitals.ts
├── setupTests.ts
└── theme
    └── index.ts

 

デザインはこんな感じです。

まとめ

この記事では、React と TypeScript を使用した ToDo アプリ開発シリーズの第 2 部を紹介しました。第 2 部では、ToDo アプリに json-server を導入し、アプリケーションのレイアウトを定義しました。json-server は簡易的なデータベースとして機能し、データを保存するサーバーとしての役割を果たします。レイアウトの定義においては、MUI をインストールしてサイドバーを配置しました。さらに、アプリケーションのテーマ設定も行いました。次回の第 3 部では、ToDo アプリの機能と API リクエストの実装を行います。