React基本事項の備忘録②

# はじめに
ProgateでのReactの第二章が終了したので、備忘録としてまとめたいと思います。

## JSXがブラウザに表示される流れ
JSXはそのままだとブラウザに表示されません。なので一旦HTMLに変換してからブラウザに渡されます。
以下のようなディレクトリ構成だと仮定します。

```php:
React
|-index.html
|-src
   |-index.js
   |-components
        |-App.js
```

## App.jsとindex.jsの関係
index.js内で`ReactDom.render(<App />, ...)`と記述することで`App.js`内のJSXがHTMLに変換されます。これは定型文のようなものです。

```php:App.js
class App extends React.Component {
  render (){
    return(
       <div>
          <h1>Hello World!</h1>
       </div>
    );
  }
}

export default App;
```

```php:index.js
import App from './components/App';
ReactDom.render(<App />, document.getElementByID('root'));
```

## index.jsとindex.htmlの関係
index.js内に`(..., document.getElementByID('root'))`と記述することで変換されたHTMLがindex.htmlの指定したid名の要素の中に格納されます。
最終的にindex.htmlの内容がブラウザに表示されます。

```php:index.js
import App from './components/App';
ReactDom.render(<App />, document.getElementByID('root'));
```

```php:index.html
<body>
  <div id="root">ここにApp.jsのreturnの内容が反映される</div> 
</body>
```

## cssを適用
index.html内でcssを読み込むことでcssを適用させることができます。

```php:index.html
<head>
  <link rel="stylesheet" href="stylesheet.css">
</head>
<body>
  <div id="root">ここにApp.jsのreturnの内容が反映される</div> 
</body>
```
JSXもHTMLと同じようにタグやクラス名を指定してcssを適用させることができます。
注意として、JSXにクラス名を付与させる場合は`className="クラス名"`と記述します。

```App.js
class App extends React.Component {
  render (){
    return(
       <div>
          <h1>アナゴ</h1>
          <h2>カツオ</h2>
          <p className="sazae">サザエ</p>
       </div>
    );
  }
}
```

```php:stylesheet.css
h1 {
  color: red;
}

h2 {
  font-size: 16px;
}

.sazae {
  color: blue;
}
```

## コンポーネント
コンポーネントとは部品やパーツという意味です。
Reactでは`見た目 + 機能 = コンポーネント` としていて、コンポーネントを組み合わせることによってWebのUIを作成していきます。

### コンポーネントの構成
今回は画面にプログラミング言語の一覧を表示させるために**Language**というコンポーネントを作成していきます。
新しくLanguage.jsというファイルを作成し、React.Componentを継承するLanguageクラスを作成します

```php:Language.js
{/* おまじない */}
import React from 'react';
{/* クラス名がコンポーネントの名前になる */}
class Language extends React.component {
  render () {
   :
   :
  }
}
```
renderメソッド内にJSXを記述していきます。

```php:Language.js
// Reactをインポート
import React from 'react';

// Languageクラスを定義
class Language extends React.Component {
  render() {
    return (
      <div className='language-item'>
        <div className='language-name'>HTML & CSS</div>
        <img className='language-image' src='HTML-CSS.png'/>
      </div>
     );
  }
}
```
このままではまだブラウザに表示されません。次にLanguage.jsがブラウザに表示されるまでの流れを整理します。
現在のディレクトリ構造は以下の通りです。

```php:
React
|-index.html
|-src
   |-index.js
   |-components
        |-App.js
        |-Language.js
```

### コンポーネントの表示①
App.js内でLanguageコンポーネントを呼び出すにはまず、コンポーネントを`export`します。

```php:Language.js
// Reactをインポート
import React from 'react';

// Languageクラスを定義
class Language extends React.Component {
  render() {
    return (
      <div className='language-item'>
        <div className='language-name'>HTML & CSS</div>
        <img className='language-image' src='HTML-CSS.png'/>
      </div>
     );
  }
}
{/* export */}
export default Language;
```

### コンポーネントの表示②
Languageコンポーネントを表示させるためには、次の２つの手順を踏みます。

**1. App.js内でコンポーネントをインポートする**
**2. App.jsのreturn内にJSXを記述する**

```php:App.js
import React from 'react';
{/*  Languageコンポーネントをインポート */}
import Language from './Language';
class App extends React.Component {
  render (){
    return(
       <div>
          <h1>言語一覧</h1>
          {/* JSXを記述 */}
          < language />
       </div>
    );
  }
}
```
これでLanguage.jsのreturnの内容がブラウザに表示されます。
またコンポーネントは何度でも呼び出せます。

```php:App.js
import React from 'react';
{/*  Languageコンポーネントをインポート */}
import Language from './Language';
class App extends React.Component {
  render (){
    return(
       <div>
          <h1>言語一覧</h1>
          < language />
          < language />
          < language />
       </div>
    );
  }
}
```
上のコードの場合HTML&CSSの同じ情報が３つ表示されています。
これを例えば、違う言語の情報を表示させたい場合は`props`という引数のようなものを用いて表示内容を変えます。

## propsとは
引数のようなもので今回の場合はApp.jsから各言語の名前と画像ファイルをLanguageコンポーネントに渡すことで言語ごとに表示を変えることができます。App.jsから渡すこれらのデータを**props**といいます。

### propsの渡し方
propsは`props名　= 値`という形でコンポーネントを渡す箇所で渡します。
今回の場合はLanguageコンポーネントにnameとimageという２つのpropsを渡します。

```App.js
render () {
  return (
    <div>
      < Language 
         name = "HTML & CSS "
         image = "HTML&CSS.png"
      />
    </div>
  )
}
```
これを各言語ごとにpropsを用意します。

```php:App.js
import React from 'react';
import Language from './Language';

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>言語一覧</h1>
        <div className='language'>
          {/* HTML & CSSのpropsを渡す */}
          < Language 
            name = "HTML & CSS"
            image = "HTML&CSS.png"
          />
          {/* JavaScriptのpropsを渡す */}
          < Language 
            name = "JavaScript"
            image ="JavaScript.png"
          />
          {/* Reactのpropsを渡す */}
          < Language 
            name = "React"
            image ="React.png"
          />
        </div>
      </div>
    );
  }
}

export default App;
```

### propsの取得
渡されたpropsは`this.props`で取得できます。this.propsはオブジェクト型で`{props名: 値}`という形になります。また、オブジェクト型なので`this.props.props名`でpropsの値を取得できます。

```Language.js
import React from 'react';

class Language extends React.Component {
  render() {
    return (
      <div className='language-item'>
        {/* props名nameの値を表示する */}
        <div className='language-name'>{ this.props.name }</div>
        
        {/* src属性の値を、props名imageの値を表示する */}
        <img 
          className='language-image'
          src={this.props.image}
        />
        
      </div>
    );
  }
}

export default Language;
```

### mapメソッド
コンポーネントを何度も呼び出す際にpropsを用意します。この時、例えば100個のpropsを用意したいときに次のように記述するのは大変です。

```App.js
render () {
  return (
    <div>
      <h1>言語一覧</h1>
       < Language name = "..." image = "..." />
       < Language name = "..." image = "..." />
       < Language name = "..." image = "..." />
       < Language name = "..." image = "..." />
       < Language name = "..." image = "..." />
       :
       :
    </div>
  )
}
```
そこでES2015から実装された`mapメソッド`を使って繰り返し処理の形で記述を簡略化していきます。

```php:App.js
render () {
  // languageListを宣言
  const languageList = [
    {name: "HTML & CSS", image: "HTML&CSS.png"},
    {name: "Javascript", image: "Javascript.png"},
    :
    :
  ]
  return (
    <div>
     　{languageList.map(( languageItem ) => {
         return(
          <Language 
             name = { languageItem.name }
             image = { languageItem.image }
          />
        );
      }
    )}
    </div>
  )
}
```
return外で定義したlanguageListをmapメソッドでlanguageItemに１つずつ格納します。
languageItemはオブジェクト型なので`languageItem.props名`で値を取得できます。
今回の場合はlanguageItem.nameとlanguageItem.imageで各言語の名前と画像ファイルを取得しています。

以上です！