さらに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コンポーネントに許します。