React入門#4 〜コンポーネント間でデータの受け渡しと再利用をする〜

## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ コンポーネントを使う理由 / 種類
・ propsでデータを受け渡す
・ 受け渡せるデータ型について

■ Reactに関する過去の記事はこちら
・ [React入門#1 〜Reactの基礎知識〜](https://qiita.com/s79ns/items/271ec50a26949e902016)
・ [React入門#2 〜JSXについて〜](https://qiita.com/s79ns/items/da61ddd58e0ac0d2baf6)
・ [React入門#3 〜create-react-appの環境構築〜](https://qiita.com/s79ns/items/69cc8e77994e90963a21)

## コンポーネントを使う理由

コンポーネントについては[こちら](https://qiita.com/s79ns/items/271ec50a26949e902016)の記事をご覧下さい。

■ なぜコンポーネントを使うのか

・ 再利用する
コンポーネントにprops（引数みたいなもの）を渡す事で、ログイン・ログアウトボタンを作る時にボタンだけコンポーネントを作っておき、文字だけを変えて再利用することができます。

・ 分割統治する
疎結合（コンポーネント同士が関連し合わない）状態で、管理がしやすいというメリットがあります。

・ 変更に強くする
コンポーネントが分かれていることにより、他要素に影響を与えず変更することができます。

## コンポーネントの種類

Reactで使うコンポーネントは大きく分けて2つあります。

#### ・ <font color = "green">Functional Component</font>

関数型で定義されたコンポーネントで、ES6のアロー関数で記述します。
基本的に`state`を持たず、`props`を引数に受け取り、JSXで記述した構文を見た目として返します。

※ `state`は次回解説しますが、現時点では、そのコンポーネントが持っている状態のこととご認識下さい。

```react:src/Article.jsx
import React from 'react';

const Article = (props) => {
    return (
        <div>
          <h2>{props.title}</h2>
        </div>
    );
};
```

#### ・ <font color = "red">Class Component</font>

クラスによって定義されたコンポーネントです。
下記例では、`Article`クラスで宣言し、`React.Component`を継承しています。
その後、`constructor`内の引数`props`を渡し、`this.props`が使えるようになります。

最終的に`this`を使って、`render`メソッド内でJSXを`return`します。

<font color="green">Functional Component</font>と比べ、記述量が増える代わりにライフサイクルや`state`を使うことができます。
※ ライフサイクルは他記事で解説しますが、現時点では、作られて消えるまでのコンポーネントの時間の流れのこととご認識下さい。

```react:src/Article.jsx
import React from 'react';

class Article extends React.Compornent {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div>
                <h2>{this.props.title}</h2>
            </div>
        );
    }
}
```

今のReactでは<font color="red">Class Component</font>よりも、<font color="green">Functional Component</font>がよく使われています。
記述がシンプルなのもありますが、なるべく`state`を持たせたくないという考え方の為です。

## 例

[前回](https://qiita.com/s79ns/items/69cc8e77994e90963a21)の記事で作成した開発環境を例にします。

#### ① srcフォルダ配下にBlog.jsxを新規作成する

srcフォルダの中にBlog.jsxというファイルを新規作成します。
Blog.jsxというファイルの下に、Article.js（記事）というコンポーネントを関連付けるように編集していきます。

![スクリーンショット 2020-12-22 16.12.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/ddfa9627-5ffc-6e6b-7f02-0fd1345aec36.png)

#### ② Blog.jsxの編集

Blog.jsxを<font color="red">Class Component</font>で記述します。
Articleコンポーネントはこれから作成しますが、JSXにArticleコンポーネントを呼び出す処理を書きます。

`export default Blog;`は、他コンポーネントにBlogクラスをエクスポートする為の記述です。

```react:src/Blog.jsx
import React from "react";

class Blog extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <Article />
      </div>
    );
  }
}

export default Blog;
```
#### ③ index.jsの編集

Blogクラスをindex.jsに呼び出したいので、`<React.StrictMode>`の中を編集し、Blogクラスをインポートします。

```react:src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Blog from './Blog';

ReactDOM.render(
  <React.StrictMode>
    <Blog />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```

これでindex.jsの中でBlogクラスのコンポーネントが使える状態になります。

#### ④ Article.jsxを新規作成する

Blog.jsxと同様に、srcフォルダの中にArticle.jsxという名前でファイルを新規作成します。

![スクリーンショット 2020-12-22 17.23.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/9e48c700-98ad-6b52-71d5-c5fbac2ba882.png)

#### ⑤ Article.jsxの編集

Article.jsxは<font color="green">Functional Component</font>で記述します。
Articleという関数を宣言し、`props`を受け取るので引数に`props`、<font color="red">Class Component</font>ではないので`constructor`を使わず`return`を書きます。
最後にAritcleのエクスポート宣言します。

```react:src/Article.jsx
import React from "react";

const Article = (props) => {
  return (
    <div>
      <h2>Reactコンポーネントの使い方</h2>
    </div>
  );
};

export default Article;
```

#### ⑥ Blog.jsxの編集（Articleのインポート）
Articleをインポートします。

```react:src/Blog.jsx
import React from "react";
import Article from "./Article";

// 以下略
```

#### ⑦ 表示内容の確認

エディタからターミナルを開き、`npm start`でローカルサーバーを起動します。

![スクリーンショット 2020-12-23 9.23.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/11598611-1d87-f391-efcf-419ae0ee2147.png)

Blogクラスの中のArticleコンポーネントの内容を表示することができました。

![スクリーンショット 2020-12-23 9.27.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/366725f1-2038-df96-785a-1b2eb7afa928.png)

※ 補足
Blog.jsxのrenderメソッド内の`div`を省略する方法についてです。

```react:src/Blog.jsx
// 中略
  render() {
    return (
      <div>
        <Article />
      </div>
    );
  }
}
export default Blog;
```

以下のように、`<Article />`が1つなら`div`を省略することが可能です。
しかし、2つ以上だとJSXではタグで囲う必要があり、エラーとなってしまうので注意です。

```react:src/Blog.jsx
// 中略
  render() {
    return (
        <Article />
    )
  }
}
export default Blog;
```

`React.Fragment`でArticleコンポーネントを囲うと、実際のHTML上ではタグとして表示されずにJSXのコンポーネントをラップすることができます。また、`<>`で記述しても同様です。

```react:src/Blog.jsx
// 中略
  render() {
    return (
        <React.Fragment>
          <Article />
          <Article />
        </React.Fragment>
    )
  }
}
export default Blog;
```

```react:src/Blog.jsx
// 中略
  render() {
    return (
        <>
          <Article />
          <Article />
        </>
    )
  }
}
export default Blog;
```

## 受け渡せるデータ型

基本的に、引数を受け渡したい時は波括弧の中にデータを記述します。（文字列のみ波括弧無しでも可）
数値・真偽値・配列・文字列・変数・オブジェクトなど何でもデータを渡すことができます。

```react:Blog.jsx
import React from 'react';
import Article from "./Article";

const authorName = "s79ns";
const Blog = () => {
    return (
        <div>
            <Article title="React"  // 文字列のみ{}無しでも可
            order={3} // 数値
            isPublished={true}  // 真偽値
            author={authorName}  // 変数
            />
        </div>
    );
};
export default Blog;
```

## 再利用する

3つ`Article title`にそれぞれ異なる文字列を入力してブラウザの画面を確認してみます。

```react:Blog.jsx
import React from "react";
import Article from "./Article";

class Blog extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <>
        <Article title="reactとは" />
        <Article title="環境構築" />
        <Article title="実際に使ってみよう" />
      </>
    );
  }
}

export default Blog;
```

```react:Article.jsx
import React from "react";

const Article = (props) => {
  return (
    <div>
      <h2>{props.title}</h2>
    </div>
  );
};

export default Article;
```

同じコンポーネントを使って、それぞれ異なる表示にすることができました。
このようにコンポーネントを再利用することで、何度も同じ記述をしなくて済みます。

![react再利用.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/8cf1e789-7027-7ea4-9f95-fd9a64cbc612.png)

更に、例えば記事タイトルの下に順番を表示したいケースの場合です。
`Article title`の横に`order`で番号を定義します。

```react:Blog.jsx
import React from "react";
import Article from "./Article";

class Blog extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <>
        <Article title={"reactとは"} order={1} />
        <Article title={"環境構築"} order={2} />
        <Article title={"実際に使ってみよう"} order={3} />
      </>
    );
  }
}

export default Blog;
```

`{props.title}`の下に、文字列`{props.order}`で呼び出します。

```react:Article.jsx
import React from "react";

const Article = (props) => {
  return (
    <div>
      <h2>{props.title}</h2>
      <p>順番は{props.order}です</p>
    </div>
  );
};

export default Article;
```

子のコンポーネントを1つ変えるだけで、親のコンポーネントから渡した引数を反映してくれます。

![react再利用order.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/0f6bcabf-72cf-4c0f-e922-df95ac4c188f.png)

## 次の記事はこちら

[React入門#5 〜stateの設定と取得と変更〜](https://qiita.com/s79ns/items/493d8acc4c347e78e333)