さらにReact
[Get started]から始めるReact開発:その1
[Get started]から始めるReact開発:その2:Rendering Elements
[Get started]から始めるReact開発:その3:Components and Props
[Get started]から始めるReact開発:その4(State and Lifecycle①
[Get started]から始めるReact開発:その4(State and Lifecycle②
Components and Props
コンポーネントはUIを独立した再利用できるピースに分けることができ、個別のそれぞれのピースについて考えることができます。
Functional and Class Components
コンポーネントを定義する最もシンプルな方法はjavascript関数を書くことです。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
この関数はデータとしてのpropsオブジェクトを引数として利用し、React要素を返すのでReactコンポーネントとして妥当なものです。
私たちはそのようなコンポーネントのことを文字通りjavascript funnctionなので"functional"と呼びます。
あなたはまた、コンポーネントの定義にES6 classを使うこともできます。
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
上記二つのコンポーネントは、Reactという観点で見れば同じものです。
クラスについては次のセクションで議論するだろう追加の特徴がいくつかあります。
それまではfunctional componentについては簡潔に利用することにしましょう。
Rendering a Component
以前、私たちはDOMタグを代表するReact要素のみに出会っていました。
const element = <div />;
しかしながら、要素はユーザー定義コンポーネントも代表することができます。
const element = <Welcome name="Sara" />;
ユーザー定義コンポーネントを代表する要素としてReactを見るときは、単一のオブジェクトとしてこのコンポーネントにJSX attributeを渡します。私たちはこのオブジェクトをpropsと呼びます。
例えば、このコードはページ上にHello, Saraを描画します。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
この例で何が起こっているかをおさらいしましょう。
- まず
<Welcome name="Sara" />と一緒にReactDOM.render()を呼び出します。 - Reactはpropsとして
{name: 'Sara'}と一緒にWelcomeコンポーネントを呼びます。 -
Welcomeコンポーネントは結果として<h1>Hello, Sara</h1>要素をを返します。 - React DOMは
<h1>Hello, Sara</h1>に合うように効率的にDOMをアップデートします。
警告
コンポーネント名は大文字で始める。
例えば<div />はDOMタグを代表していますが、<Welcome />はコンポーネントを代表し、<Welcome />にスコープがあることを要求します。
Composing Components
コンポーネントはそれらのアウトプットの中で他のコンポーネントを参照できます。これによりどのレベルの詳細にも同じコンポーネント抽象化を使用できます。ボタン、フォーム、ダイアログ、スクリーン。Reactアプリは全て、それらはコンポーネントとして共通の表現がされます。
例えば、なんどもWelcomeをレンダリングするAppコンポーネントを作れます。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
通常、新しいReact Appsは一番上にシングルAppコンポーネントを持っています。しかしながらもし、既にあるAppにReactを統合する場合は、ボタンのような小さいコンポーネントから逆さまに始まるかもしれないし、徐々にビュー階層の一番上に向かって作業をするかもしれません。
警告
コンポーネントは単一のルート要素を返さなければなりません。これは全ての<Welcome />要素を含むように<div>を追加する理由となります。
Extracting Components
小さなコンポーネントにコンポーネントを分割することを恐れないでください。
例えばCommentコンポーネントについて考えます。
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
propsとしてauther(オブジェクト),text(文字列),date(date オブジェクト?)を受け入れて、ソーシャルメディア上でコメントを述べます。
このコンポーネントは全てネストされているため、変更が複雑になりますしそれ自体のいち部分を個別に再利用することも難しくなっています。それではここから幾つかのコンポーネントを抜き出してみましょう。
最初にAvatorを抜き取ってみましょう
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
AvatorはCommentの中でレンダリングされていることを知る必要はありません。これはautherではなくより一般的な名前としてのuserをpropに与えている理由です。
私たちはほんの少しだけコメントをすぐに単純化できます。
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
次に、私たちはuser's nameに隣接するAvatarをレンダリングするUserInfoコンポーネントを抜き取ってみましょう。
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
これはさらにCommentを単純化することができます。
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
コンポーネントの抽出は最初は単調な仕事のように見えるが、再利用可能なコンポーネントのパレットを持つことは大きなアプリでこそうまくいく。
大まかに良い方法としては、あなたのUIの一部で幾つかの部品(ButtonやPanelやAvatar)を使用している場合や、それ自身(App, FeedStory, Comment)が十分に複雑な場合には、再利用可能なコンポーネントの良い候補となります。
Props are Read-Only
functionやclassとしてコンポーネントを宣言したとしても、それ自身のpropsを変更してはいけません。sum関数について考えます。
function sum(a, b) {
return a + b;
}
このような関数はそれらの入力の変更を行わず、いつも同じ入力に対して同じ結果を返すのでpureと呼ばれています。
対象的に、この関数は自身の入力を変更しているのでimpureです。
function withdraw(account, amount) {
account.total -= amount;
}
Reactはとても柔軟ではありますが、一つ厳格なルールを持っています。
All React components must act like pure functions with respect to their props.
全てのReactコンポーネントはそれらのpropsを尊重し純粋関数のように動かなければならない。
もちろん、アプリケーションUIはダイナミックで時間とともに変わります。次のセクションではstateの新しいコンセプトを紹介しましょう。
Stateはこのルールに違反することなくユーザーアクションやネットワークレスポンスや他の何かしらに反応して時間とともにそれらの出力を変更することをReactコンポーネントに許します。