ReactとPython flaskを使ってWebアプリを作りたい

# はじめに

仕事でReactによるフロント開発に携わり始めたので、アウトプットの練習も兼ねて簡易webアプリを作成しました。

どんなアプリにするかアイデアはまったく思い浮かばなかったので、手元にあった[mecab](https://taku910.github.io/mecab/)を使った分かち書きスクリプトを使って、フロントで受け取った入力テキストをサーバー側で分かち書きをし、その結果をフロントで表示するという非常にシンプルなアプリです。
(主目的はreactとflaskをつなぐ部分を勉強することだったため、アプリの見た目や機能は全然作り込んでいませんのであしからず。)

表題の通り、フロント側はReact、サーバー側はpython flaskで実装しています。

今回実装したスクリプトは[こちら](https://github.com/Pu-of-Parari/jparser_app)で公開しています。

# 完成品
画面
![app_top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269076/d9e948c8-adf0-b093-af85-0d714430b522.png)

分かち書きしてみる
![app_res.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269076/3b6e42c7-b428-9340-8466-b5a02845a1cc.png)

# 実装環境
```
OS: Ubuntu 18.04.2 LTS
Python: 3.6
flask==1.0.2

npm: 6.14.7
```

reactの環境構築については今回触れませんが、公式チュートリアルが日本語でも充実していて非常に参考になりました。
- https://ja.reactjs.org/

こちらもすごくおすすめです。
- https://mae.chab.in/archives/2529

# 実装する
## 構成図
今回実装したアプリの構成は以下のようになっています(主要部分のみ)。

![app_architect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269076/aa9a2442-d1da-3509-aafb-36201312077a.png)


## サーバー側
サーバー側は以下のような構成になっています。

```
backend/
   ├─ requirements.txt
   ├─ server.py
   └─ utils.py

```

`server.py`はflaskサーバーを立ち上げるコードです。

アドレスやポートは一番下、`app.run(host='127.0.0.1', port=5000)`で指定します。

```python:server.py
from flask import Flask
from flask import request, make_response, jsonify
from flask_cors import CORS
from utils import wakati

app = Flask(__name__, static_folder="./build/static", template_folder="./build")
CORS(app) #Cross Origin Resource Sharing

@app.route("/", methods=['GET'])
def index():
    return "text parser:)"

@app.route("/wakati", methods=['GET','POST'])
def parse():
    #print(request.get_json()) # -> {'post_text': 'テストテストテスト'}
    data = request.get_json()
    text = data['post_text']

    res = wakati(text)
    response = {'result': res}
    #print(response)
    return make_response(jsonify(response))

if __name__ == "__main__":
    app.debug = True
    app.run(host='127.0.0.1', port=5000)

```

`@app.route("/wakati", methods=['GET','POST')`部分でフロントからテキストを受け取り、分かち書き処理した後、フロントへ返す処理をしています。
`data = request.get_json()`によってフロントからポストされてきた内容をjson形式で取得します。
ここから必要なデータを取り出して、何らかの処理(関数にかけたり、DBに入れたりし)をし、`response = {'result': res}`のようにjson形式にしてフロントに返します。


(補足：CORSとは)
別リソースへアクセス(＝クロスサイトHTTPリクエスト)できるようにするために必要なルールです。これがないとフロント側から立ち上げたflaskサーバへアクセスできません。
- 参考：https://aloerina01.github.io/blog/2016-10-13-1


## フロント側
今回は`create-react-app`の雛形を用いました。
(create-react-appの設定および使い方は[こちら](https://www.to-r.net/media/react-tutorial12/)が非常にわかりやすいです！)

フロント側は以下のような構成になっています(主要ファイルのみ掲載)。

```
frontend/app/
   ├─ node_modules/
   ├─ public/
   ├─ src/
   |   ├─ App.css
   |   ├─ App.js
   |   ├─ index.js
   |   └─ ...
   └─ ...

```

自動生成された雛形の中の`App.js`を以下のように書き換えました。

```javascript:App.js
import React from 'react';
import './App.css';
import Axios from 'axios';

//function App() {
export class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <h1>text parser</h1>
          <form onSubmit={this.handleSubmit}>
            <label>
              <textarea name="text" cols="80" rows="4" value={this.state.value} onChange={this.handleChange} />
            </label>
            <br/>
            <input type="submit" value="Parse" />
          </form>
        </header>
      </div>
    );
  }


  wakati = text => {
    //console.log("input text >>"+text)
    Axios.post('http://127.0.0.1:5000/wakati', {
      post_text: text
    }).then(function(res) {
      alert(res.data.result);
    })
  };

  handleSubmit = event => {
    this.wakati(this.state.value)
    event.preventDefault();
  };

  handleChange = event => {
    this.setState({ value: event.target.value });
  };
}

export default App;

```


この中の以下の部分でサーバー側とのやり取りを行なっています。

```javascript
  wakati = text => {
    //console.log("input text >>"+text)
    Axios.post('http://127.0.0.1:5000/wakati', {
      post_text: text
    }).then(function(res) {
      alert(res.data.result);
    })
  };
```

`server.py`で立てた`http://127.0.0.1:5000/wakati`に`this.state.value`の値をポストします。
サーバー側で処理された後、返ってきた`result`の値が`alert(res.data.result);`によってブラウザに表示されます。

# 動かす
フロントエンド/バックエンド用にそれぞれターミナルを立ち上げて以下のコマンドを実行します。

サーバー側

```
$ cd backend
$ python server.py
```

フロント側

```
$ cd frontend/app
$ yarn start
```

ブラウザから`localhost:3000`にアクセスすることでアプリを利用できます(yarn startで自動で立ち上がります)。

# おわりに
今回はReactとPython flaskを用いて簡易的なWebアプリを実装しました。
簡易的とはいえ、短時間で楽にWebアプリを実装できるので素晴らしいですね。

フロント修行中の身なので、見た目や機能についてはまだまだなのでご意見、アドバイス等いただければ幸いです。
最後まで読んでいただきありがとうございました！