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')
);

Try it on CodePen.

この例で何が起こるかを見てみましょう:

  1. ReactDOM.render()<Welcome name =" Sara "/>を呼んでいます。
  2. Welcome 'コンポーネントを {name:' Sara '} `props付で与呼んでいます。
  3. Welcomeコンポーネントは結果として<h1> Hello、Sara </ h1>を返します。
  4. 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')
);

Try it on CodePen.

例によって、上部には単一の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>
  );
}

Try it on CodePen.

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>
  );
}

Try it on CodePen.

コンポーネントの抽出は、最初は面倒な作業のように思えるかもしれませんが、
再利用可能なコンポーネントの引き出しを持つことは、より大きなアプリケーションで効果的です。 UIの一部が(Button、Panel、Avatar)何度か使用されている場合や、
またはそれ自身で十分複雑な場合(App、FeedStory、Commentなど)、
それは再利用可能なコンポーネントとなる良い候補でしょう。

propは読み取り専用です

コンポーネントを(関数またはクラスとして)宣言しても、
それは自分自身の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コンポーネントが、
このルールに違反することなく、ユーザアクション、ネットワークレスポンス、
およびその他の何らかの要求に応答して、時間の経過とともに出力を変更できるようにします。

⚠️ **GitHub.com Fallback** ⚠️