05. Components and Props - accgetter/React GitHub Wiki
コンポーネントを使用すると、UIを独立した再利用可能な部分に分割し、
各部分について個別に考えることができます。
概念的には、コンポーネントはJavaScript関数のようなものです。
彼らは任意の入力(「prop」と呼ばれる)を受け入れ、
何がスクリーンに現れるべきかを記述するReact Elementsを返します。
コンポーネントを定義する最も簡単な方法は、JavaScript関数を記述することです。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
この関数は、データを含む単一の "props"オブジェクト引数を受け取り、
React Elementsを返すための、有効なReactコンポーネントです。
このようなコンポーネントは、JavaScript関数であるため、文字通り"functional"と呼んでいます。
また、ES6 class
を使用してコンポーネントを定義することもできます
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
上記の2つのElementsは、Reactの観点からは同等です。
クラスには、next sectionsで説明するいくつかの追加機能があります。
それまでは、機能部品を簡潔に使用します。
以前は、DOMタグを表示するReact Elementsだけでした。
const element = <div />;
ただし、elementはユーザー定義のコンポーネントを表示することもできます。
const element = <Welcome name="Sara" />;
Reactはユーザー定義のコンポーネントを表すelementとわかると、
JSX属性を単一のオブジェクトとしてこのコンポーネントに渡します。
このオブジェクトを「prop」と呼びます。
たとえば、次のコードでは、ページに「Hello、Sara」と表示されます。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
この例で何が起こるかを見てみましょう:
-
ReactDOM.render()
で<Welcome name =" Sara "/>
を呼んでいます。 -
Welcome 'コンポーネントを
{name:' Sara '} `props付で与呼んでいます。 -
Welcome
コンポーネントは結果として<h1> Hello、Sara </ h1>
を返します。 - React DOMは効率的にDOMを更新し、
<h1> Hello、Sara </ h1>
と一致させます。
警告:
コンポーネント名は常に大文字で開始します。
例えば、
<div />
はDOMタグを表しますが、<Welcome />
はコンポーネントを表し、Welcome
をスコープに入れる必要があります。
コンポーネントは、出力の際、他のコンポーネントを参照できます。
これにより、どのレベルのでも同じようにコンポーネントの抽象化をすることができます。
ボタン、フォーム、ダイアログ、スクリーン: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')
);
例によって、上部には単一のAppコンポーネントがあります。
しかし、Reactを既存のアプリケーションに統合する場合は、
「Button」のような小さなコンポーネントでボトムアップを開始し、
徐々にビュー階層の最上位に向かって作業を進めるほうがいいかもしれません。
警告:
コンポーネントは単一のルートを返す必要があります。すべての
<Welcome />
を含むために<div>
を追加したのはそのためです。
コンポーネント小さくに分割するのを恐れないでください。
例えば、この 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>
);
}
author
(オブジェクト)、 text
(文字列)、 date
(日付)をpropsとして受け取り、
ソーシャルメディアのWebサイトにコメントを記述します。
このコンポーネントは、すべてネストしているために変更するのが難しく、
個々の部分を再利用することが困難です。
なのでいくつかのコンポーネントを抽出しましょう。
まず、「アバター」を抽出します:
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
Avatar
は Comment
の中でレンダリングされていることを知る必要はありません。
これは私たちがそのpropに author
ではなく user
というより一般的な名前を与えた理由です。
使用されている文脈ではなく、
コンポーネントの独自の視点から名前を付けることをお勧めします。
Comment
も少し単純化することができます:
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>
);
}
次に、ユーザ名の隣に 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など)、
それは再利用可能なコンポーネントとなる良い候補でしょう。
コンポーネントを(関数またはクラスとして)宣言しても、
それは自分自身のpropを決して変更してはいけません。この sum
関数を考えてみましょう:
function sum(a, b) {
return a + b;
}
そのような関数は、入力を変更しようとせず、常に同じ入力に対して同じ結果を返すので、
"pure"と呼ばれます。
対照的に、この関数は、それ自身の入力を変更するため、pureではありません。
function withdraw(account, amount) {
account.total -= amount;
}
Reactは非常に柔軟ですが、厳密に1つのルールがあります:
すべてのReactコンポーネントは、そのpropに関してpure関数のように動作しなければなりません。
もちろん、UIは動的であり、時間とともに変化します。
next sectionでは、
「state」の新しい概念を紹介します。stateは、Reactコンポーネントが、
このルールに違反することなく、ユーザアクション、ネットワークレスポンス、
およびその他の何らかの要求に応答して、時間の経過とともに出力を変更できるようにします。