☘️

4つの方法でpropsを受け取ってみる

2022/06/09に公開

はじめに

ReactとTypeScriptを勉強している中で、propsの受け取り方や型定義の定義があいまいだったので整理してみました。

実践

準備

create-react-appを使用してReact環境の構築は完了している前提で進めます。
まず、srcフォルダ下に「index.tsx」「TodoList.tsx(親コンポーネントのファイル)」「Todoitem.tsx(子コンポーネントのファイル)」のファイルを作成して、「index.tsx」「TodoList.tsx」には以下のコードを書きます。

src/index.tsx
import { StrictMode } from "react";
import * as ReactDOMClient from "react-dom/client";
import { TodoLists } from "./TodoLists";

const rootElement = document.getElementById("root");
const root = ReactDOMClient.createRoot(rootElement);

root.render(
  <StrictMode>
    <>
      <h1>Todo</h1>
      <TodoLists />
    </>
  </StrictMode>
);
src/TodoLists.tsx
import { TodoItem } from "./TodoItem";

//todosオブジェクトの型を定義
export type Todo = {
  id: number;
  title: string;
};

export const TodoLists = () => {
  const todos: Todo[] = [
    {
      id: 1,
      title: "task1"
    },
    {
      id: 2,
      title: "task2"
    },
    {
      id: 3,
      title: "task3"
    }
  ];
  //TodoItemにtodosオブジェクトを渡す。
  return <TodoItem todos={todos}></TodoItem>;
};

propsを受け取る

propsの受け取り方としては、

  1. 子コンポーネントに該当するファイル内で型エイリアス(またはインターフェース)を書くかどうか
  2. propsの受け取り方を分割代入するかどうか

で引数の書き方は変わってくると思います。したがって、書き方としては4種類あります。

①型エイリアスを書かない&propsを分割代入しない

まずはシンプルに、型エイリアスを書かずにpropsを書いてみます。
propsはオブジェクトなので、{ todos: Todo[] }と型定義します。

src/TodoItem.tsx
import { Todo } from "./TodoLists";

export const TodoItem = (props: {todos:Todo[]}) => {
  return (
    <>
      <ul>
        {todos.map((todo) => {
          return <li key={props.todo.id.toString()}>{props.todo.title}</li>;
        })}
      </ul>
    </>
  );
};

こんな感じで描画されると思います。

シンプルですが、この方法はTodoItemコンポーネント内で受けとったpropsを使うときに、必ず値の前にpropsを書かないといけません。

②型エイリアスを書かない&propsを分割代入する

分割代入することで値の前にpropsを記載する必要はなくなりコード量も減ります。

src/TodoItem.tsx
import { Todo } from "./TodoLists";

export const TodoItem = ({ todos }: { todos: Todo[] }) => {
  return (
    <>
      <ul>
        {todos.map((todo) => {
          return <li key={todo.id.toString()}>{todo.title}</li>;
        })}
      </ul>
    </>
  );
};

propsを受け取る値が増えると、型定義するコードも増えて引数のコード量が増えて可読性が落ちると思います。

③型エイリアスを書く&propsを分割代入する

型エイリアスを書くことでTodoItemコンポーネントの引数が増えても、型定義ではPropsを書くだけです。

src/TodoItem.tsx
import { Todo } from "./TodoLists";

type Props = {
  todos: Todo[];
};

export const TodoItem = ({ todos }: Props) => {
  return (
    <>
      <ul>
        {todos.map((todo) => {
          return <li key={todo.id.toString()}>{todo.title}</li>;
        })}
      </ul>
    </>
  );
};

④型エイリアスを書く&propsを分割代入する

一応、子コンポーネントで型エイリアスを書く&propsを分割代入しない方法も紹介します。

src/TodoItem.tsx
import { Todo } from "./TodoLists";

type Props = {
  todos: Todo[];
};

export const TodoItem = (props: Props) => {
  return (
    <>
      <ul>
        {props.todos.map((todo) => {
          return <li key={props.todo.id.toString()}>{props.todo.title}</li>;
        })}
      </ul>
    </>
  );
};

以上から、個人的にpropsの書き方は③がベストプラクティスかなと思います。
最後までお読みいただきありがとうございました。
気になる点などありましたら、コメントいただけると嬉しいです。

こちらにデモアプリを作成しました。

GitHubで編集を提案

Discussion