はじめに
Fullstack React: 30 Days of React の意訳です。
ちょいちょい読んでるのでせっかくなので訳そうと思った次第。飽きるまで続きます。かなり意訳です。
本編
Day3で最初のコンポーネントを作ることができたので、もうすこし面白いコンポーネントを作ってみましょう。Day4からはより複雑なコンポーネントの作成方法をみていきます。
※これはキャプチャですが、本家のほうではReactによってレンダリングされたHTMLになってます
よく見るインターフェースであるタイムラインを考えましょう。FacebookやTwitterでイベントの履歴などを表示するアレです。
もちろんタイムライン全体を1つのコンポーネントとして作成することもできますが、単一クラスが大きくなりすぎ、テスタビリティが低下するため、あまりいいアイディアではありません。
// Don't do it like this. This is for example only
// このようにしてはいけません!!これはダメな例です!!
class Panel extends React.Component {
render() {
return (
<div className="notificationsFrame">
<div className="panel">
<div className="header">
<div className="menuIcon">
<div className="dashTop"></div>
<div className="dashBottom"></div>
<div className="circle"></div>
</div>
<span className="title">Timeline</span>
<input
type="text"
className="searchInput"
placeholder="Search ..." />
<div className="fa fa-search searchIcon"></div>
</div>
<div className="content">
<div className="line"></div>
<div className="item">
<div className="avatar">
<img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
Doug
</div>
<span className="time">
An hour ago
</span>
<p>Ate lunch</p>
</div>
<div className="item">
<div className="avatar">
<img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
</div>
<span className="time">10 am</span>
<p>Read Day two article</p>
</div>
<div className="item">
<div className="avatar">
<img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
</div>
<span className="time">10 am</span>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
</div>
<div className="item">
<div className="avatar">
<img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
</div>
<span className="time">2:21 pm</span>
<p>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</p>
</div>
</div>
</div>
</div>
)
}
}
Breaking it down
では、単一のコンポーネントで構築するのではなく、複数のコンポーネントに分割してみましょう。このコンポーネントを見ると大きく分けて2つのコンポーネントがあります。
- タイトルバー
- コンテンツ
さらにコンテンツ部分をそれぞれの関心(アバター、タイムスタンプ、テキスト)に分割すると、3つのコンポーネントに分けることができます。
もっと言うと、タイトルバーをタイトル、メニューバー、検索アイコンに分割することができます。ここではやりませんが、必要ならできるということです。分割をどこまでやるのかを決めるのは科学というより芸術なのです(要はケースバイケースや好みによるので勝手に考えてねってこと)。
いずれにしても、アプリケーションをコンポーネントとして分割できないか考えることは良いことです。それによって、テスタビリティが向上し、機能ごとの場所がハッキリするからです。
The container component
タイムラインアプリをつくるために、まずはアプリ全体を入れるコンテナコンポーネントを作りましょう。コンテナは単に他の2つのコンポーネント(タイトルバーとコンテンツ)のラッパーになるでしょう。
このコンポーネントは特別な機能を(まだ)必要としないため、HelloWorldコンポーネントと似たように、レンダーだけを持つコンポーネントとなります。
class App extends React.Component {
render() {
return (
<div className="notificationsFrame">
<div className="panel">
{/* content goes here */}
</div>
</div>
)
}
}
classNameはJSXの記法です。詳しくはDay2。
Child components
あるコンポーネントは他のコンポーネントをネストすることができます。ネストしている方を親コンポーネント、ネストされている方を子コンポーネントと呼びます。
ラッパーコンポーネントが出来たので、元のソースコードをコピペしてタイトルバーとコンテンツのコンポーネントを構築することができます。
class Header extends React.Component {
render() {
return (
<div className="header">
<div className="fa fa-more"></div>
<span className="title">Timeline</span>
<input
type="text"
className="searchInput"
placeholder="Search ..." />
<div className="fa fa-search searchIcon"></div>
</div>
)
}
}
最後にコンテンツコンポーネントを構築します。各タイムライン要素は、単一のコンポーネントとして、アバター、タイムスタンプ、テキストを持ちます。
class Content extends React.Component {
render() {
return (
<div className="content">
<div className="line"></div>
{/* Timeline item */}
<div className="item">
<div className="avatar">
<img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
Doug
</div>
<span className="time">
An hour ago
</span>
<p>Ate lunch</p>
<div className="commentCount">
2
</div>
</div>
{/* ... */}
</div>
)
}
}
React内でコメントを書くためには、
{ /* コメント */ }
を使います。
Putting it all together
ヘッダーコンポーネントとコンテンツコンポーネントができたので、これらをAppコンポーネントに組み込んでみましょう。普通のHTMLの要素のように扱うことができるのが良いところです。
class App extends React.Component {
render() {
return (
<div className="notificationsFrame">
<div className="panel">
<Header />
<Content />
</div>
</div>
)
}
}
これで複数のコンポーネントを組み合わせて、コンポーネントをつくる方法がわかりました。
ただ、このアプリにはまだユーザ操作やカスタムデータを扱っていません。Reactを使ってこれらを扱うのは素のHTMLよりも簡単です。
Day5からはよりダイナミックでデータ駆動なReactについて学んでいきます。