なんとなく、簡単に入門できそうなReact

タイトルが強弁すぎますね、ごめんなさい😂

[すすさんの記事](https://qiita.com/susu_susu__/items/da94e751d2db784ad0ee)のリリースツイートを見て「おっこれはワイもReact記事書くムーブかな？？？」となったので書いてみます。

# 本項のゴール
+ Reactのコンポーネントの作り方を理解する
+ propsを渡して動的にUIを作ってみる(Stateは気力があれば別記事で書こうと思います)

# 諸注意
間違ってる箇所とかバッドプラクティスがあるかもしれません
コメントで指摘していただければと思います。

# そもそもReactってなに？
フロントのUIライブラリの話になるとVueと比較される事が多いので高機能なのを想像しがちですが
React自体、及びReact-DOMは **HTMLのレンダリングをするだけのライブラリです。**

そもそもReact自体はHTML周りの機能すら持ってません。その辺りは色々あってReact-DOMに分割されました。

この話についてはGoogleで検索するといくらでも出てくるので本稿では省略します。

# HTMLをそのまま書いていくのとどう違う？
HTMLを直書きして `document.querySelector('div#hoge').~~~` のようにJSでターゲットを指定して操作するの（いわゆるDOM操作）も悪くはないですが、UI部品が増えると似たようなコードが増え、非常にメンテナンスのしづらい煩雑なコードになっていきます。

またUIを小分けにせずHTMLに全てベタ書きすると
どこからがNavの部分でどこからがメインビューなのかわかりづらくなります。

これを解決するのがReactです。

# Reactだと何が良いのか
Reactを使うことによって何がどう変わるのか、という話ですが結論的には以下のようになります。

+ JSの中にHTMLを混ぜたような文が書ける(ビューに出す要素とJSで操作する部分を纏めて書ける)
+ UIパーツをコンポーネントという単位で小分けしながら作れる

あんまり話が長くなっても面白くないので実際に作りましょう。

# 実際に作る-環境を建てる
注意事項です。

### nodeとnpmはインストール済みである前提で解説します。

まだされていない方はnodenv等でインストールをしておいてください。
nodeのバージョンは偶数系が無難です。(Firebaseに興味があるとかでなければv10以降がおすすめ)

### ES6の構文については先に理解をしておいてください。

主に `const` `let` `()=>` `import, export`が多用されます。これらが何なのか知らない方は[MDNドキュメント](https://developer.mozilla.org/ja/docs/Web/JavaScript/A_re-introduction_to_JavaScript)を先に参照していただくか、Googleで検索していただくことをおすすめします。

---------

```bash
$ npx create-react-app sample
```
このコマンドを叩くと `./sample/` の中にReactのアプリの開発に必要なものがすべてインストールされます。あるオプションを入れるとTypeScriptを使うようにすることもできますが今回は省略します。

```bash
$ cd sample/
$ npm start 
```
`package.json` のあるディレクトリで `npm start` を叩くことで開発サーバが立ちあがり、自動的にブラウザにlocalhostのビューが出てきます。こんなの。
![Screen Shot 2020-03-16 at 23.52.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320738/12f55982-58ee-f3a2-08e2-24e6c42d49f7.png)

とりあえずこれで問題なく動くことは確認できました。
このテンプレートをそのまま加工してもいいですが、とりあえず今回はネイティブな状態に戻すため `src/`にあるものを全て消して、`index.js`を新規作成してください。
おそらくエラーが出ますが一旦無視で構いません。

# 実際に作る-HTMLをレンダリングしてみる
先程作った`index.js`に追記してみてください。

```jsx:index.js
import React from 'react';
import ReactDOM from 'react-dom';

const App = () => {
  return (
    <div>
      <h1>Hello Mr.React!</h1>
    </div>
  );
};

ReactDOM.render(<App />, document.querySelector('div#root'));
```

順を追って説明します。
まず2行目まででReact、そしてReact-DOMを呼び出して使えるようにします。
ちなみに2行目のReact-DOMは使わない限りはimportしなくて大丈夫です。

```jsx
const App = () => {
  return (
    <div>
      <h1>Hello Mr.React!</h1>
    </div>
  );
};
```
Reactではコンポーネントを作る際に **大文字から始まる関数オブジェクト** を用いてオブジェクトの体型を表現します。
**大文字から**という一文は絶対守ってください。小文字だと蹴られます。

また、Reactアプリケーションの開発においてはよくHTML(XML)をそのまま書けるようにJSXという特殊なフォーマットを使います。
これはbabelという変換器を使ってブラウザも理解できるJSの構文に変換をしています。
(一般的にJSXを使う場合は拡張子を `.jsx` にして明示します。`index.js`は例外)

そしてこのJSXにも制限があり、**復数の要素をルートに横並びさせることができません**。
必ず1つの要素の下に居る必要があります。回避する方法もありますがこちらは後述しますので一旦忘れてください。

このAppというコンポーネントは、単純に `<div>` の中に`<h1>~~~</h1>`を包んだものを返しているだけです。
変化したりとかもさせていません。

ちなみにクラスの構文でも表現できますが個人的には関数オブジェクトでの宣言がおすすめです。(理由とかはまた機会があれば)


```jsx
ReactDOM.render(<App />, document.querySelector('div#root'));
```

そして、そのAppのコンポーネントを`ReactDOM.render`に渡すことで指定したターゲット( `public/index.html` にある)にレンダリングされる、という流れになっています。

実際に追記されるとこのように出ます。

![Screen Shot 2020-03-17 at 0.51.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320738/bfa221d5-9c43-ba22-7b9a-e323a03a0f66.png)

これだけしか出ませんが、正常です。次に進みましょう。

----

### ここまでで覚えておくこと
+ コンポーネントは関数もしくはクラスで宣言して作る
+ コンポーネント命名は頭文字が大文字である必要あり(小文字だとHTMLと解釈される)
+ コンポーネントを使うときは `<ComponentName />` のようにタグっぽい文法で書く
+ HTML(XML)を記述して `return` することでレンダリングされる

# 実際に作る-表を作ってみる(+コンポーネントを分ける)

多分ネイティブなReactを触る上で一番恩恵デカイのが表の生成だと思うのでそれで試してみようと思います。
まずは表を表現するためのコンポーネントを新しいファイルに分けて生成します。
今回は`table.jsx`というファイル名で作ります。

```jsx:table.jsx
const Head = () => {
  // theadの構成を作る
};

const Body = () => {
  // tbodyの構成を作る
};

export default function Table(){
  return(
    <table>
      <Head />
      <Body />
    </table>
  )
};
```

`index.js`でコンポーネントを受け取れないと困るので、テーブル本体を返すコンポーネントのみ`export`修飾子で渡せるようにしておきます。 `default`は気にすんな

そして`index.js`で受け取りをして、レンダリングをさせます。

```jsx:index.js
import React from 'react';
import ReactDOM from 'react-dom';
// `table.jsx` からTableをimportする
import Table from './table';

const App = () => {
  return (
    <div>
      <h1>Hello Mr.React!</h1>
      <Table />
    </div>
  );
};

ReactDOM.render(<App />, document.querySelector('div#root'));
```

受け取り側のコードが書けたので、表の実装に入ります。
しかし、`Table`コンポーネントの中に全ての構成を突っ込むとコードがかなり長くなってしまうので、Reactの得意分野を活かして`Head`と`Body`の2つのコンポーネントに分けてそれぞれ別々にレンダリングしようと思います。

## Headを作る

それでは `Head` から作っていこう、と言いたいところですがストップです。
`Table`コンポーネントのところでヘッダー行の名前や数量を配列で表現することで動的に変更できる、といった構造に出来ればかなり改変がしやすくなるような気がします。長年の勘がそう言っています。

そのためには、先程作った`Table`コンポーネントに少しだけ変更を加えます。

```jsx
export default function Table(){
  // 配列を入れた変数を追加
  const headList = ['ID', 'Name', 'isOtaku'];

  // `<Head>` の横に`list={headList}` と追記
  return(
    <table>
      <Head list={headList}/>
      <Body />
    </table>
  )
};
```

追記した `<Head list={}>`ですが、これは**props**と呼ばれており、コンポーネントに対してデータを渡すことができる仕組みです。
今回の場合`list`というpropsの中に`headList`という配列を渡しています。
これを `Head` のコンポーネントの中で取得する際は以下のコードのようになります。

```jsx
// 引数に `props` が入ってくる必要がある
const Head = (props) => {
  // `props.~~~` でpropsの中身を参照できる
  const array = props.headList;
};
```

試しに`console.log(array);`と書いて保存してみてください。
![Screen Shot 2020-03-17 at 23.49.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320738/99919cc8-b9c1-ee0f-9de8-db71d2acd604.png)

こんな感じでコンポーネント側に配列が渡されていることが確認できます。
あとは`Array.map`で回しながら`<th></th>`の中に内包してやれば `head` は完成です。
`Head` の完成形としてはこんな感じになりました。

```jsx
const Head = (props) => {
  // `props.~~~` でpropsの中身を参照できる
  console.log(props.list);

  return (
    <thead>
      <tr>
        { props.list.map((item) => {
          return (
            <th>
              { item }
            </th>
          );
        }) }
      </tr>
    </thead>
  );
};
```

少し難解ですが`()`の中の`{}`で括った部分はJSのコードとして評価されるので、これを利用して`map`で回しながら`<th>`を生成し、その中に配列の要素を挿入することでヘッダー行が出来上がりです。

## Bodyを作る

続いて`Body`コンポーネントも作っていきます。
こちらも同様に変数を渡すことで動的に生成させようと思います。そのためには配列の中にオブジェクトを入れるのが最適かなあという感じなので、`Table`の中身をこうしてみます。

```jsx
export default function Table(props){
  const headList = ['ID', 'Name', 'isOtaku'];
  
// tbodyを構成するためのオブジェクトの集まりを作る
  const bodyElements = [
    {
      id: 1,
      name: 'Sister Cleaire',
      isOtaku: false
    },
    {
      id: 2,
      name: 'Yashiro Kidsuku',
      isOtaku: true
    },
    {
      id: 3,
      name: 'Otogibara Era',
      isOtaku: true
    }
  ];
  return(
    <table>
      <Head list={headList}/>
      <Body list={bodyElements} />
    </table>
  )
};
```

ここでやっていることも同じで、オブジェクトの入った配列をprops経由で渡しているだけです。
あとは`Body`コンポーネント内でループなどの実装をすればOKです。

```jsx
const Body = (props) => {
  // `<tr>`を纏めて生成するための
  // ローカル内のコンポーネント
  const Tds = (props) => {
    return(
      <>
        <td>
          {props.object.id}
        </td>

        <td>
          {props.object.name}
        </td>

        <td>
          {props.object.isOtaku.toString()}
        </td>
     </>

    );
  };

  return(
    <tbody>
      { props.list.map((item) => {
        return(
          <tr>
            <Tds object={item} />
          </tr>
        );
      }) }
    </tbody>
  )
};
```

少しややこしいですが落ち着いて、まずは`return`内部から入りましょう。

```jsx
return(
    <tbody>
      { props.list.map((item) => {
        return(
          <tr>
            <Tds object={item} />
          </tr>
        );
      }) }
    </tbody>
  )
```

`<tbody>`の中で配列を`map`を使ってループさせ、`<Tds>`をレンダリングしています。
このときに配列の中に入っていたオブジェクトが一つずつ`props.object`として入ります。
このことを抑えて`Tds`を見てみましょう。

```jsx
const Tds = (props) => {
  return(
    <>
      <td>
        {props.object.id}
      </td>

      <td>
        {props.object.name}
      </td>

      <td>
        {props.object.isOtaku.toString()}
      </td>
     </>
  );
};
```

`Tds`は複数の`<td>`タグを返すことから命名しています。
復数の `<td>` タグの中で `props.object` で渡されたオブジェクトの値を参照しています。
また、`isOtaku`だけ真理値型なので文字列に明示的に変換しています。

ここで「**おい待てや**」ってなった方は優秀です。最初のあたりで説明したことを思い出してください。

> そしてこのJSXにも制限があり、**復数の要素をルートに横並びさせることができません**。

そう、横並びした`<td>`は通常だと返せません。そう。**通常は**。
ここで登場するのが `<>` `</>` というカオナシのようなやつです。
これは`React.Fragment`と呼ばれるコンポーネントの糖衣構文で、これに包むとレンダリングの際に**横並びした状態で**レンダリングしてくれます。
今回はこれを利用することで横並びする要素をそのまま分離しています。


これでレンダリングするものが完成です。
保存していただいて、表がきちんと出来ていればOKです。
また、配列を減らしたり増やしたりして行が増減するのを確認してみてください。

![Screen Shot 2020-03-18 at 0.48.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320738/acb41bb8-cbe1-2d64-ee0e-4545e6521ad3.png)

----

### ここまでで覚えておくこと
+ コンポーネントを小分けにしつつ、propsで値をバケツリレーして作ると煩雑化が防げる
+ propsを使う際はコンポーネントの引数を入れることを忘れないようにする(必要なければ入れなくてOK)

# おわりに
今回はReactのさわりのさわりだけ解説してみましたがいかがでしょうか。
Reactは自分でコンポーネントを作るだけでなく、npmからパッケージを引っ張ってimportすることでそのまま利用することもできます。
その時の話は[ここ](https://qiita.com/huequica/items/b945147371f8b19b97c9)で纏めてありますので、そちらもよかったらぜひご覧いただければと思います。

ちなみに今回のサンプルで作ったソースコードは以下に全て放り込んでおいたので、上手く行かなかった場合は見比べてみてください。
https://github.com/huequica/qiita_react_sample

それでは今回はこの辺で。