LoginSignup
1
6

More than 1 year has passed since last update.

[React] React+TypeScript 実践

Posted at

React初心者がReact+TypeScriptについて勉強した時のメモです。

型がないせいでバグっている例

ボタンを押したらJSONPlaceholderのTodoのデータをaxiosを使ってデータ取得するプログラム。
https://jsonplaceholder.typicode.com/todos

App.tsx
import axios from "axios";
import { useState } from "react";
import { Todo } from "./Todo";

export default function App() {
  const [todos, setTodos] = useState<any>([]);
  const onClickFetchData = () => {
    axios.get("https://jsonplaceholder.typicode.com/todos").then((res) => {
      setTodos(res.data);
      console.log(res);
    });
  };
  return (
    <div className="App">
      <button onClick={onClickFetchData}>データ取得</button>
      {todos.map((todo) => (
        <Todo title={todo.title} userid={todo.userid} />
      ))}
    </div>
  );
}
Todo.tsx
export const Todo = (props) => {
  const { title, userid } = props;
  return <p>{`${title}(ユーザー:${userid})`}</p>;
};

データ取得したらユーザー名がundefinedになるというバグが発生している。

取得データに型を定義する

App.tsx
import axios from "axios";
import { useState } from "react";
import { Todo } from "./Todo";

type TodoType = {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
};

export default function App() {
  const [todos, setTodos] = useState<Array<TodoType>>([]);
  const onClickFetchData = () => {
    axios
      .get<Array<TodoType>>("https://jsonplaceholder.typicode.com/todos")
      .then((res) => {
        setTodos(res.data);
      });
  };
  return (
    <div className="App">
      <button onClick={onClickFetchData}>データ取得</button>
      {todos.map((todo) => (
        <Todo key={todo.id} title={todo.title} userid={todo.userId} />
      ))}
    </div>
  );
}

取得するデータにtypeとして型を定義する。
axiosのget部分とuseStateの部分に取得データの型を当てることエディターの補完も効くようになりどこが間違っているかが分かる。
今回の場合は、以下の部分のuseridのiが小文字になっていたからというのが分かった。

 <Todo title={todo.title} userid={todo.userid} />

propsに型定義

type TodoType = {
  userId: number;
  title: string;
};

export const Todo = (props: TodoType) => {
  const { title, userId } = props;
  return <p>{`${title}(ユーザー:${userId})`}</p>;
};

propsも同様に型を定義しておくことでiの小文字に気づけバグを防げる。

PickとOmit

型定義の部分(今回でいうTodoType)を切り出した場合に型を呼び出す際にPickかOmitを使うことで効率的に管理できる。

  • 切り出したTodoType
types/todo.ts
export type TodoType = {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
};
  • Pick(抽出)
import { TodoType } from "./types/todo"

export const Todo = (props: Pick<TodoType, "userId" | "title">) => {
  const { title, userId } = props;
  return <p>{`${title}(ユーザー:${userId})`}</p>;
};

Pickを使うことでこのコンポーネントで必要な型の情報のみ抜き出せる。

  • Omit(省略)
import { TodoType } from "./types/todo"

export const Todo = (props: Omit<TodoType, "id" | "completed">) => {
  const { title, userId } = props;
  return <p>{`${title}(ユーザー:${userId})`}</p>;
};

OmitPickの逆でTodoTypeの中から必要ないものを除いた形。

コンポーネント自体の型

export const Todo: FC<Pick<TodoType, "userId" | "title">> = (props) => {
  const { title, userId } = props;
  return <p>{`${title}(ユーザー:${userId})`}</p>;
};

関数コンポーネント自体の型定義。

1
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
6