こんにちは、i3DESIGNエンジニアの田口です。
今回は「React初学者が必ず押さえておきたい考え方とは?」というテーマでお話します。
こちらの記事は、下記のような方を対象としています。
- プログラミングを学習中でフロントエンドの技術に興味のある方
- Reactを触ったことはないが、興味がある方
私自身が、HTML, CSS, Pug, Sass, JavaScriptでの開発から、Reactでの開発に移行してからの約半年で感じた体験をもとにお話し致します。
目次
Reactとは?
Reactとは、Facebook社とコミュニティによって開発されているユーザーインターフェース(UI)構築の為のJavaScriptライブラリです。
実は、Reactはフレームワークではなく、ライブラリです。(Vue.jsやAngular.jsはフレームワーク、jQueryはライブラリ)小さく始められることができる点が特徴です。(既存サイトのチャットボットのみReactで開発する、等)
Reactでは、WEBページを操作するためのDOM(Document Object Model)操作において、仮想DOMを使用して実際のDOMとの差分のみを描画する事で、大規模な開発でもレンダリングコストが高くなりづらいという特徴があります。
また、WEB開発用としてReact.js、ネイティブアプリ開発用としてReact Nativeがあり、ほぼ同じ書き方でWEBアプリもスマホのネイティブアプリも開発できるのも魅力の一つです。
そのパフォーマンスや開発効率の高さから、実際に多くの有名IT企業がReactで開発を行っています。
- Airbnb
- Netflix
- メルカリ
などがReactを用いて開発を行っています。
React初学者が必ず押さえておきたい考え方とは?
では、本題ですが、「React初学者が必ず押さえておきたい考え方」とはなんでしょうか?
それは、
「コンポーネント指向の考え方」
です。
コンポーネント指向とは、ソフトウェア開発において部品ごとに小さく分けて開発する考え方のことです。
Reactで開発する上で非常に重要な概念なのですが、意外とフォーカスされないと思いましたので、取り上げて説明していきます。
Reactはコンポーネント指向のライブラリ
まず、Reactはコンポーネント指向を前提として作られたライブラリです。
Reactにおいてコンポーネントとは、マークアップなどの見た目とロジック機能を分離せず合わさったもの、と定義しています。(実際は保守性やテストの観点から、見た目とロジック機能を分離させて開発することが多いです)
React公式サイトでも、TOPページのど真ん中に特徴として下記のように説明されています。
「コンポーネントベース 自分自身の状態を管理するカプセル化されたコンポーネントをまず作成し、これらを組み合わせることで複雑なユーザインターフェイスを構築します。」
参考URL:https://ja.reactjs.org/
ここでいう「カプセル化されたコンポーネント」とは何でしょうか?
カプセル化は、下記のように説明できます。
「カプセル化とは、オブジェクト指向プログラミングにおいて、互いに関連するデータの集合とそれらに対する操作をオブジェクトとして一つの単位にまとめ、外部に対して必要な情報や手続きのみを提供すること。外から直に参照や操作をする必要のない内部の状態や構造は秘匿される。」
http://e-words.jp/w/%E3%82%AB%E3%83%97%E3%82%BB%E3%83%AB%E5%8C%96.html
要するに、処理に必要な変数や値をコンポーネントに渡すだけで、そのコンポーネントの中身を見ることなく、処理を完結できるようにすることです。
かなり乱暴な例えですが、洋服を洗濯をするとき、洗濯機の構造や原理を意識せずとも、洗濯物を入れてボタンを押せば、洋服がきれいになることをイメージしてください。
洗濯機に渡すのは、洋服とボタンを押すという動作だけです。
上記のようなReactのコンポーネント指向は、ソフトウェア設計の考え方のひとつ「分割統治法」やReactの公式ドキュメントで例に挙げられている「単一責任の原則」が似たような考え方です。
イメージとして、
分割統治法
↓
単一責任の原則
↓
コンポーネント指向(コンポーネントベース)
という順に概念が具体的になっていきます。
分割統治法
分割統治法とは、大きな問題を小さく分割して解決していく手法です。ソフトウェア開発においては、大きなソフトウェアを一気に作るのではなく、できるだけ分割して、影響の範囲を限定し、一つ一つ完成させていく方法です。
この考え方はReactだけでなく、ソフトウェア開発全般、問題解決全般に応用できる考え方です。
「アプリを開発する」といった大きな課題に対して、ユーザーに提供する価値を決める、要件を決める、技術選定をする、など小さな課題にしていくことも分割統治法の一つです。
ソフトウェア開発においては、その責任、責務を軸に、独立して設計できる部分に分割し、開発する方法です。
参考URL:https://www.atmarkit.co.jp/ait/articles/1706/01/news166.html
単一責任の原則
モジュールやクラスをカプセル化し、その役割が単一の疎結合の状態にするという考え方です。お互い影響を及ぼし合わないという考え方です。
Reactでは、「ひとつのコンポーネントは理想的にはひとつのことだけをするべきだ」という考えがあります。
コンポーネントの肥大化を避け、小さなコンポーネントに分けることが推奨されています。
より良い設計とは、疎結合で依存性の少ない設計です。単一責任の原則で言えばクラスの変更理由(役割)が1つであれば良い設計といえます。
https://thinkit.co.jp/article/13274
単一責任の原則 (single responsibility principle) があり、これはすなわち、ひとつのコンポーネントは理想的にはひとつのことだけをするべきだということです。将来、コンポーネントが肥大化してしまった場合には、小さなコンポーネントに分割するべきです。
https://ja.reactjs.org/docs/thinking-in-react.html#step-1-break-the-ui-into-a-component-hierarchy
コンポーネント指向のメリット、デメリット
上記の考え方を踏まえた上で、コンポーネント指向で開発するメリットとデメリットについて具体的に説明をしていきます。
メリット:影響範囲が限定されるため、保守運用がしやすい
カプセル化されることで、コンポーネントの影響範囲が限定されるようになるため、保守運用をしやすくなります。
例えば、HTMLとCSSで書かれた見た目のスタイルを変更する際、CSSのクラス名はグローバルに影響するため、クラス名の重複があったときはレイアウトが崩れ破綻する原因になります。そのため、BEMやFLOCSSなどの命名規則を設けて、クラス名の衝突が起きないようにする必要があります。
一方、CSS in JSやCSS Modulesを使用してコンポーネント内でカプセル化されたCSSを使用する場合、他のコンポーネントで同じクラス名が使用されていたとしても、クラス名の衝突が起きません(厳密には、衝突しないように自動的にランダムな命名に変換されています)
また、可読性が向上することでの保守運用のしやすさもあります。
例えば、プログラムにエラーがあったときに、500行のコードを読むのと、50行のコードを読むのではどちらの方が楽でしょうか?
コンポーネント指向で小さなコンポーネントに分割されていれば、細かく見なくてはいけない内容が限定され、コードを読む時間も短縮することができます。
メリット:パーツの再利用がしやすく、拡張しやすい
コンポーネントを分けることで、パーツの再利用性を上げ、拡張しやすくなります。
例えば、検索窓としての機能は同じでスタイルを変えて使用する、ボタンとしての機能は同じで中身の文字だけ変えて使用する、など別なページでの再利用がしやすくなります。
更に、Material UIなどのReactコンポーネントライブラリも充実しているので、効率的に開発を行うことができます。
参考URL:https://material-ui.com/
デメリット:コンポーネントを分ける粒度、分け方が人によって異なる
Reactのコンポーネント指向のメリットをお話してきましたが、デメリットに関してもお伝えします。
コンポーネント指向のデメリットは、コンポーネントを分ける粒度、分け方が開発者によって異なる、ということです。そのため、少し時間をかけてすり合わせをしていく必要があります。
例えば、虫メガネのアイコン付きの検索窓があったときに、全体で最小単位のコンポーネントにするのか、検索窓と虫メガネのアイコンは別なコンポーネントにするのか、など開発者によって分ける粒度の意見が異なることが多いので、プロジェクトごとに決めていく必要があります。デザインは開発に直結するので、エンジニア間だけでなく、デザイナーとも粒度を合わせていく必要もあります。
対応策として、Atomic Designの思想を取り込んでプロジェクト内でコンポーネント分割の考え方を最適化するという方法があります。Atomic Designもすべてに対して最適解ではないので、サービスや規模に応じてカスタマイズしていくのが良いと思います。
コンポーネント指向の例
最後に、Reactの公式ドキュメントからコンポーネント指向で分割した実例を簡単に紹介します。
参考URL:https://ja.reactjs.org/docs/thinking-in-react.html#start-with-a-mock
下の画面が、検索可能な商品データ表です。商品名を検索するとカテゴリ別に商品名と価格が表示される機能があります。
このアプリをコンポーネント思考で分割していくと、下記のようになります。
FilterableProductTable: このサンプル全体を含む
SearchBar: すべてのユーザ入力を受け付ける
ProductTable: ユーザ入力に基づくデータの集合を表示・フィルタする
ProductCategoryRow: カテゴリを見出しとして表示する
ProductRow: 各商品を1行で表示する
細かい説明は公式に記載されているので、今回は割愛しますが、それぞれのコンポーネントの責任、責務によって分割されているのがわかるかと思います。
世界中で使用されるFacebookやInstagramも、このようなコンポーネント思考で開発され、拡張性と保守性を両立しながらサービスを広げています。
まとめ
いかがでしたでしょうか?
今回は、「React初学者が必ず押さえておきたい考え方」としてコンポーネント指向の考え方を紹介しました。
アイスリーデザインでは、フロントエンド技術のメインとしてReactを使用しており、直近のコーポレートサイトリニューアルでも、ReactのフレームワークであるNext.jsを使用して開発を行いました。