はじめに
最近、React開発を始めたばかりのフロントエンドエンジニアです。
ReactでライフサイクルやState管理など、理解はできてきたものの、
コンポーネントが複雑化してきて、非常に困っていたため、
整理のために書きました。
なにかご指摘がありましたら、積極的にコメントをいただけるとありがたいです。
とりあえず、考えることは一つ!
Reactのコンポーネントを役割で分ける、ということ!
具体的にいうと、コンポーネントを
レンダリングを担当するもの
データ構造や、データの流れを担当するもの
に分けます。
その二つについて、解説していきます
※内容的には、Reduxの公式(http://redux.js.org/docs/basics/UsageWithReact.html)
に乗っているものと同じ内容ですが、Reduxを使っていなくても、コンポーネントの整理には有効かと思います。
#レンダリングを担当するもの(Presentational Component)
Presentatinal Componentは、
どのように見えるかのみに焦点をあてたコンポーネントで、propsで与えられたデータで、レンダリング時にどう表現するかを記述します。
そのため状態を持つ必要がないので、Reactを継承しなくて軽いStateless Functional Componentで記述します。
(※propsで渡ってくる値を一般化すると汎用性が増す
悪い例:
import Task from '/template/Task'
export default class ParentPage extends React.Component {
...
<Task openTaskDetail={()=>this.openTaskDetail()} />
...
}
で渡し、
const Task = (props) => {
return (<h1 onClick={props.openTaskDetail} >Click!!</h1>)
}
で発火
いい例:
import Task from '/template/Task'
export default class ParentPage extends React.Component {
...
<Task handleClick={()=>this.openTaskDetail()} />
...
}
で渡し、
const Task = (props) => {
return (<h1 onClick={props.handleClick} >Click!!</h1>)
}
で発火
#データ構造や、データの流れを担当するもの(Container Component)
Presentetional Componentを内包し、
基本DOMの構成はせず、
Presentational Componentへのpropsの受け渡しを担当する。
データの生成もここで行う。
そのため、どのように見えるかについてはまったく関与しなくて良い
(※Container Componentでデータを渡すときは、何をレンダリングするコンポーネントに渡しているかが、わかりやすい下位コンポーネントを持つべき
悪い例:
<TitleText name={shop.name} />
<FlexRow>
<Circle badge={shop.cart} />
<Circle badge={shop.customer} />
</FlexRow>
<Number number={shop.tel} />
<GrayText text={shop.information} />
良い(?)例:
import ShopStatus from '../template/ShopStatus'
import ShopInformation from '../template/ShopInformation'
<ShopStatus name={shop.name} badgeCart={shop.cart} badgeCustomer={shop.customer} />
<ShopInformation tel={shop.tel} information={shop.information} />
// こっちの方が、コンポーネントが値をなんのために渡しているのか、わかりやすい!
#まとめ
コンポーネントは
Presentatinal Componentは、レンダリング
Container Componentは、データ構造や、データの流れに対して責任を持つ
で分けよう。
それを理解した上で、Atomic Designの考え方を取り入れると整理されて、とてもソースが見やすくなる、、、はず!!