🐣 React実践の教科書 P215〜225
作成日: 2022/01/08
1

今日やったこと

  • 「モダンJavaScriptの基本から始める React実践の教科書」 P215〜225
    • 8-2 APIで取得するデータへの型定義
    • 8-3 Propsへの型定義

学習メモ

データの一覧が表示されるアプリをTypeScriptに書き換える
APIを呼ぶと以下のような一覧データが取得できる

例:エンドポイント

https:// example.com/users

例:取得結果

[
	{
		"id": 1,
		"name": "主田",
		"age": 24,
		"personalColor": "blue"
	},
	{
		"id": 2,
		"name": "先岡",
		"age": 28,
		"personalColor": "pink"
	},
	{
		"id": 3,
		"name": "後藤",
		"age": 23,
		"personalColor": "green"
	},
]

TypeScript化後のフォルダ構成

App.tsx

import { useEffect, useState } from "react";
import { ListItem } from "./components/ListItem";
import axios from "axios";

export const App = () => {
  // 取得したユーザー情報
  const [users, setUsers] = useState([]);

  // 画面表示時にユーザー情報取得
  useEffect(() => {
    axios.get("https://example.com/users").then((res) => {
      setUsers(res.data);
    })
  }, []);

  return (
    <div>
      {users.map(user => (
        <ListItem id={user.id} name={user.nama} age={user.age} />
      ))}
    </div>
  );
};

ListItem.tsx

export const ListItem = props => {
    const { id, name, age} = props;
    return (
        <p>
            {id}:{name}{(age)}
        </p>
    );
};
  • axios はHTTP通信をするためのライブラリで、API通信の際によく使われるもの
    • ここではAPIを呼んで、取得データをStateに設定している

上記のコードでは、App.tsxでListItem.tsxにPropsを渡す部分がnameではなくnamaになってしまっている

      {users.map(user => (
        <ListItem id={user.id} name={user.nama} age={user.age} />
      ))}

このような打ち間違いでアプリがおかしくなるケースを、TypeScript使って解決する

取得データへの型定義

「どんなデータが取れるか」というのをあらかじめ型定義しておくことで、フロントエンドのコード内でのバグを減らすことができる

App.tsx(型定義を追加)

import { useEffect, useState } from "react";
import { ListItem } from "./components/ListItem";
import axios from "axios";

// ユーザー情報の型定義
type User = {
  id: number;
  name: string;
  age: number;
  personalColor: string;
};

export const App = () => {
  // 取得したユーザー情報
  const [users, setUsers] = useState<User[]>([]);

  // 画面表示時にユーザー情報取得
  useEffect(() => {
    axios.get<User[]>("https://example.com/users").then((res) => {
      setUsers(res.data);
    })
  }, []);

  return (
    <div>
      {users.map(user => (
        <ListItem id={user.id} name={user.nama} age={user.age} />
      ))}
    </div>
  );
};
  • 今回APIで取得できるのはid,name,age,personalColorの4つなのでそれをtypeとしてそれぞれstring、 numberで定義
  • axiosの場合はget<型>のようにジェネリクスで型を設定するだけでOK
    • Stateにも同じ型を指定(今回の場合はUserの配列)

この対応により、出力結果にエラーメッセージが表示されるようになり
「いざ本番環境で動かしてみたらおかしかった」という事態を避けることができる
スクリーンショット 2022-01-09 0.07.27.png

また、型を指定することでエディタで補完が利くようになるため、
例えばuser.までを入力すると「こういうプロパティがあるよ!」と表示してくれる。
上下カーソルで選択してEnterを押すだけで良いので入力する手間がはぶける
スクリーンショット 2022-01-09 0.11.20.png

  • APIなどは基本的にどんなデータが取れるかわからないので、事前に型を定義しておくことでより安全に開発を進めることができる
  • また、バックエンドチームとフロントエンドチームでAPIの認識を合わせる際にも非常に有用

Propsへの型定義

取得データやStateに型を付与することはできたが、現段階ではPropsに対する型定義はされていないので、
以下のようにPropsをnamaに打ち間違えてしまうと先ほどと同じようなバグが起きてしまう

    <div>
      {users.map(user => (
        <ListItem id={user.id} nama={user.name} age={user.age} />
      ))}
    </div>

そのため、Propsに対しても型を定義する

ListItem.tsx

// Propsの型定義
type User = {
    id: number;
    name: string;
    age: number;
}

export const ListItem = (props:User) => {
    const { id, name, age} = props;
    return (
        <p>
            {id}:{name}{(age)}
        </p>
    );
};

このように型を指定すると、先ほどと同様にエラーメッセージが表示されるようになる
スクリーンショット 2022-01-09 1.10.52.png

また、試しにnameを消してみると定義しているはずの型がPropsに指定されていない場合もエラーが検出されることが分かる
スクリーンショット 2022-01-09 1.13.43.png

TypeScriptがリファクタリングに強い理由

追加で文字色をpersonalColorにする修正が入ったため
コンポーネントに新しくPropsを追加する

まずは型定義を修正

ListItem.tsx

// Propsの型定義
type User = {
    id: number;
    name: string;
    age: number;
    personalColor: string;
}

必要な型がないというエラーが出る
スクリーンショット 2022-01-09 1.31.40.png

Props に personalColorを追加する

ListItem.tsx

// Propsの型定義
type User = {
    id: number;
    name: string;
    age: number;
    personalColor: string;
}

export const ListItem = (props:User) => {
    const { id, name, age, personalColor } = props;
    return (
        <p style="{{ color: personalColor }}">
            {id}:{name}{(age)}
        </p>
    );
};

App.tsx

      {users.map(user => (
        <ListItem id={user.id} name={user.name} age={user.age} personalColor={user.personalColor}/>
      ))}

このように、機能追加の際にまず型定義から修正していくことで、型定義をしたあとにエラーになった箇所を対応していけば良いので影響範囲がわかりやすくなる
TypeScriptがリファクタリングに強いと言われるのはこのため

所感

TypeScriptの利点について学びました。
一度設定すれば後々楽になるので積極的に使っていきたいです。