素人基盤エンジニアがDockerでDjango REST Frameworkとreactを触るシリーズ③：reactの導入


[素人基盤エンジニアがDockerでDjango REST Frameworkとreactを触るシリーズ②：Django REST Framework](https://qiita.com/LittleGreenMen/items/1c09bb1e2241a5d750fa)のつづき。
[①からみたい場合はこちら。素人基盤エンジニアがDockerでDjango REST Frameworkとreactを触るシリーズ①：Djangoの導入](https://qiita.com/LittleGreenMen/items/f60c5a8c5138ddaaed79)

# reactの導入
最終的には、S3上にreactのアプリを配置してCloudFront経由で表示させたいが、構築/テストまでは同じEC2上でreactとdocker上のDjango REST frameworkを動作させて連携させることとする。
動作が確認出来たら、ビルドしS3に移行する。
### node.jsの導入
reactのビルド環境として、node.jsが必要なので、下記手順に従いインストールする。
https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html

```shell
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
```
```shell
. ~/.nvm/nvm.sh
```
```shell
nvm install node
```
```shell
node -e "console.log('Running Node.js ' + process.version)"
```
Running Node.js v15.12.0
↑のような形でバージョンが表示されたらインストールは完了。

### create-react-app
今回は、reactアプリを簡単に作成することができるツールであるcreate-react-appを利用する。
（本格的にreactアプリを作成したい場合は自分で一から作成したほうが良いと思うが、今回はあくまでreactとDjango REST Frameworkを利用してとりあえず動くものを作るというところを目標とする。）
djangoのためのファイル群をbackendというディレクトリに作成したので、一旦/home/ec2-userまで戻り、下記コマンドを実行する。

```shell
cd /home/ec2-user
npm install -g yarn
yarn global add create-react-app
create-react-app frontend
```
しばらくすると、frontendというディレクトリが作成され、下記のような構成になっているはず。

```text
frontend
∟node_modules
　∟パッケージ多数
∟package.json
∟public
　∟favicon.ico
　∟index.html
　∟logo192.png
　∟logo512.png
　∟manifest.json
　∟robots.txt
∟README.md
∟src
　∟App.css
　∟App.test.js
　∟index.js
　∟reportWebVitals.js
　∟App.js
　∟index.css
　∟logo.svg
　∟setupTests.js
∟yarn.lock
```
まずはデフォルトの状態で、reactアプリを起動させてみる。

```shell
cd frontend
yarn start
```
http://\<ip-address>:3000
にアクセスする。
![DRF011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369619/8185a218-992a-358e-949e-44ea465c5c8b.png)
reactアプリが動作していることがわかる。
ctrl+Cで一旦終了し、下記ソースを修正してみる。

```html:public/index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet">
    <title>ReactSampleApp</title>
  </head>
  <body>
    <h1 class="title">ToDo Apps(React+DjangoRestFramework)</h1>
    <div id="root"></div>
  </body>
</html>
```

```js:src/App.js
import React, { Component } from 'react';
import axios from 'axios';

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            todos: [],
            hostname: ""
        };
    }

    componentDidMount() {
        this.getTodos();
        this.getHostname();
    }

    getTodos() {
        axios
            .get('http://<ip-address>:8000/api/todos/')
            .then(res => {
                this.setState({ todos: res.data });
            })
            .catch(err => {
                console.log(err);
            });
    }

    getHostname() {
        axios
            .get('http://<ip-address>:8000/api/hostname/')
            .then(res => {
                this.setState({ hostname: res.data });
            })
            .catch(err => {
                console.log(err);
            });
    }

    render() {
        return (
            <div>
                {this.state.todos.map(item => (
                    <div key={item.id}>
                        <h2>{item.title}</h2>
                        <p className="item_body">{item.body}</p>
                    </div>
                ))}

                <div className="box30">
                    <div className="box-title">HOSTNAME</div>
                    <p>{this.state.hostname.hostname}</p>
                </div>
            </div>
        );
    }
}

export default App;
```
\<ip-address>の部分を、EC2のIPアドレスにすることを忘れないように注意。
ここは、CloudFrontでの構成に移行すればIPアドレスを書かなくてもよくなる。

```css:src/index.css
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

h1.title {
  font-family: 'Segoe Print',sans-serif;
  padding: 0.5em;
  color: #494949;/*文字色*/
  background: #fffaf4;/*背景色*/
  border-left: solid 5px #ffaf58;/*左線（実線 太さ 色）*/
}

.box30 {
    margin: 0 auto 0 20px;
    width: 300px;
    background: #f1f1f1;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.22);
}
.box30 .box-title {
    font-size: 1.2em;
    background: #5fc2f5;
    padding: 4px;
    text-align: center;
    color: #FFF;
    font-weight: bold;
    letter-spacing: 0.05em;
}
.box30 p {
    text-align: center;
    padding: 15px 20px;
    margin: 0 0;
}

h2 {
  position: relative;
  padding: 8px 15px;
  margin-left: 40px;
  background: #def3ff;
  border-radius: 20px;
}

h2:before {
  font-family: "Font Awesome 5 Free";
  content: "\f111";
  position: absolute;
  font-size: 15px;
  left: -40px;
  bottom: 0;
  color: #def3ff;
}

h2:after {
  font-family: "Font Awesome 5 Free";
  content: "\f111";
  position: absolute;
  font-size: 23px;
  left: -23px;
  bottom: 0;
  color: #def3ff;
}

p.item_body {
  font-family: 'Mv Boli',sans-serif;
  margin-left: 80px;
}
```
ソース内で、axiosというパッケージを利用しているので、frontendディレクトリで下記コマンドを利用してパッケージを追加しておく。

```shell
yarn add axios
```


また、Django側の設定も、別サイトからのクロスオリジンアクセスがあるため、下記のように書き換える。

```python:backend/todo_project/settings.py
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

CORS_ORIGIN_ALLOW_ALL = True
```
一行目のcorsheaders～と最後のCORS_ORIGIN_ALLOW_ALLを追加。

docker-compose upでdbとdjangoのコンテナを起動する。
（この後reactも起動したいのでバックエンドで起動する。）

```shell
cd backend
docker-compose up &
```

コンテナを起動させたまま、reactを起動。

```shell
cd ../frontend
yarn start
```

http://\<ip-address>:3000/
にアクセスしてみる。
![DRF012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369619/9afc086b-0891-891f-f5c5-ee3ea89e7747.png)

無事、todoとhostnameが表示されていることがわかる。
次回は、今回構築したreactアプリをビルドしS3へ配置して最終系であるCloudfrontの形に変更する。

[つづく](https://qiita.com/LittleGreenMen/items/e5aa54f8b58efcb62769)