Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

「prop-types」でPropsのデータ型を担保する

基礎からはじめるReact入門 第7回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2018/03/30 14:00

 Reactはコンポーネントを組み合わせて開発を行うことで、保守性の高いアプリケーションを実現できるライブラリです。同時に、優れたUIを提供するライブラリでもあります。今回は、Propsの型を定義することでコンポーネントの可用性を向上させる方法を学びましょう。

目次

対象読者

  • JavaScriptとWeb開発の基礎に理解がある方
  • Reactに興味/関心があり、これから学び始める方

前提環境

 筆者の検証環境は以下の通りです。

  • macOS Sierra 10.12
  • Node.js v8.9.4/npm 5.6.0
  • React 16.2.0
  • prop-types 15.6.0

Propsにはどんなデータを渡せばよいのか

 Reactを使う機会が増えていくにつれて、他人が作ったコンポーネントを触る機会も増えていきます。連載第3回の「React×Material-UIでモダンなUIを実装する」で取り上げたmaterial-uiなどは典型的な「他人が作ったコンポーネント」ですね。数カ月前の自分自身が書いたコードも他人のものと考えたほうがいい、とする説もあるので、一人で開発していても期間が長くなれば、見覚えがないコンポーネントをメンテナンスする機会はやはり増えていくと思ったほうがいいでしょう。

 さて、他人が作ったコンポーネントを使う場合、どんなことで困るでしょうか。例として、第4回の「Reactによるフォーム/リストの基本」に出てきたリスト1のコンポーネントについて考えてみます。

リスト1 Listコンポーネント
<List
  posts={this.state.posts} />

 Listコンポーネントは、配列形式の投稿データ(posts)を受け取ることで投稿を並べて表示する機能を持ったコンポーネントでした。所定のデータ形式でデータを渡せば、よしなに表示してくれる。適切な粒度の責務を持った良いコンポーネントです。

 さて、ここで問題になるのが「postsに渡す『所定のデータ形式』とは一体何なのか」ということです。実装を見に行けば分かる、というのはごもっともなのですが、コンポーネントの実装コードの中から「this.props.***」を一つひとつ探して、そのデータ型が何なのかを推測していくのは、根気のいる作業ですね。

 では、コンポーネント一つひとつにPropsのデータ型を記述した仕様書を書けばよいのでしょうか。それとも、それに近い内容のコメントを記述しておけばよいのでしょうか。

 恐らく、それらの方法はあまり現実的ではありません。プログラムを変更したら仕様書を変更する文化自体は悪いものではありませんが、コンポーネント単位で行うのは、あまりにも膨大で煩雑な作業になってしまいます。

 Propsの型を簡単に知るための、良い方法がほしいところです。

prop-types

 もし、コンポーネントのコード内にPropsの型が書いてあって、その型の通りにデータが渡されているのかをチェックしてくれる機構があれば、別途仕様書を用意したり、仕様書通りにPropsが渡せているかチェックしたりといった、根気の必要な作業をする必要がなくなります。

 こうした課題を解決するためにFacebookが用意しているのが、今回紹介する「prop-types」というライブラリです。これは、Propsの型情報をJavaScriptのコードとして定義し、コンポーネントに付加情報として加えることで、Propsに渡されたデータをチェックできるようになるツールです。

 導入するにはリスト2のコマンドを実行します。

リスト2 prop-typesを導入するコマンド
$ npm install prop-types

 以降、本記事では、ライブラリ名を「prop-types」、ライブラリからインポートしたモジュール名を「PropTypes」、コンポーネントに定義するプロパティ名(次項で紹介します)を「propTypes」と表記します。

コンポーネントへの定義

 イメージをつかんでもらうために、前述のListコンポーネントに型情報を付加した場合のサンプルを紹介します(リスト3)。

リスト3 ListコンポーネントのpropTypesプロパティの定義
import PropTypes from 'prop-types';

class List extends Component {
  render() { ... }
}

List.propTypes = { // (1)
  // posts属性は配列である
  posts: PropTypes.arrayOf(
    PropTypes.shape({ // 各プロパティの型を明示する
      // nameは文字列型の必須項目
      name: PropTypes.string.isRequired,
      // ageは配列のうちどれかひとつに一致する必須項目
      age: PropTypes.oneOf([
        "teen",
        "twenties",
        "thirties",
        "fourties",
        "fifties"
      ]).isRequired,
      // bodyは文字列型の必須項目
      body: PropTypes.string.isRequired
    })
  )
};

 prop-typesライブラリを用いた型情報は、(1)のようにコンポーネントに「propTypes」という名前のオブジェクト型プロパティを追加することで定義されます。細かい記法については後述しますが、リスト3のサンプルを眺めてみると「posts」がどんな構造を持ったデータなのか、少し分かってくるのではないでしょうか。

チェック機構

 コンポーネントに型情報を定義できたことで型を認識しやすくなりましたが、prop-typesライブラリの本来の機能はデータのチェックです。propTypesプロパティに定義した型と異なる構造のデータが渡された場合に、コンソールにエラーログが表示されます。

 例として、先ほどpropTypesプロパティを定義したListコンポーネントに、bodyを数値型にしたオブジェクトを渡してみましょう。bodyは文字列型で定義したので、何らかの反応があるはずです。

リスト4 bodyの型が誤っているデータを渡してみる
<List
  posts={[
    { name: "taro", age: "teen", body: 0 }
  ]} />

 このコードを実行すると、コンソールには図1のエラーメッセージが表示されます。

図1 prop-typesのエラーメッセージ
図1 prop-typesのエラーメッセージ

 数値型ではなく文字列型を期待していると警告されました。コンポーネントの使い方を誤った場合には、こうして警告を出してもらえるので、デバッグ時には非常に有用です。

 ただし、これはあくまでも警告です。今回のケースでも、0はテキストとして問題なく表示されました。アプリケーションを強制終了させる形でエラーの存在を認識させるタイプのツールではなく、エラーログを監視することでデバッグをやりやすくするツールとして認識してください。

[コラム]React.PropTypes

 インターネット上でReactについての古い文献を調べると、次のような呼び出し方をしているサンプルに遭遇することがあります。

import { Component, PropTypes } from 'react';

 実は、Reactのバージョン15系までは、PropTypesモジュールはReactの一部として提供されていました。2017年の夏、Reactがバージョン16.0.0になったタイミングで、諸事情から独立したライブラリとして提供されることになり、現在に至ります。そんなわけで、今回紹介するprop-typesライブラリのバージョンは独立当時のReactのバージョンである15.6.0がそのまま使われているのです。

 2017年以前の文献を検索する際には、こうした事情に留意してください。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト 中川幸哉(ナカガワユキヤ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2017年5月時点での登録メンバは52名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂き...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

バックナンバー

連載:基礎からはじめるReact入門

もっと読む

All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5