25

投稿日

更新日

初めてフロントエンドとバックエンドの連携(Flask+React)をやってみた時の疑問と対処法

jQuery全盛期にフロントエンドエンジニアをやっていたんですが、JavaScriptにめっきり触れなくなって最近はPythonで小物を作っているという私がやってみた時の疑問です。

ディレクトリ構成はどうすれば良いの?

とりあえず分けておくのが良さそうなので、プロジェクトフォルダの下にfrontendとbackendを作りました。

  • my_project
    • frontend
    • backend

プロジェクトフォルダの下にfrontendという名前でreactのアプリを作成します。

npx create-react-app frontend

バックエンド側はbackendフォルダの下に…

gitのリポジトリは分けたほうが良いの?

Render.comを使いたくて、リポジトリは2つ必要?と思いましたが、一つのリポジトリで問題ありませんでした。

フロントエンド

  • name:my_project
  • TYPE:Static Site
  • Root Directory:frontend

バックエンド

  • name:my_project-backend
  • TYPE:Web Service
  • Root Directory:backend

という感じで2つのサイトを登録してRoot Directoryにそれぞれのディレクトリを指定することで、GitHubの一つのリポジトリを参照させることができました。

ポート問題

Flaskのデフォルトポートは5000番ですが、MacのAirPlay等の別サービスが既に使用していると、OSError: [Errno 98] Address already in useのようなエラーが発生します。Flaskで使用するポートは下記のように指定できます。

Python
if __name__ == '__main__':
    app.run(debug=True, host='localhost', port=8000)

いまどきの非同期通信はどうやって書くの?

fetchを使います。具体的な書き方は後述。
Fetch_API

CORS

CORSの設定なしでフロントエンドからバックエンドにアクセスしようとすると、下記のようなエラーが表示されてしまいます。

Access to fetch at 'http://localhost:8000/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

CORSは無闇に別のオリジンからの要求を受け入れないようにするため、アクセスを許可しても良いオリジンを制限するものです。

pip install Flask-Cors

でインストールし、制限なしでとりあえず試すだけの場合は、

Python
from flask import Flask
from flask_cors import CORS

app = Flask(__name__)

CORS(app)

としてからPythonのコードを書いていきます。

参考
Flask-CORS

フロントエンド側は、先ほどのfetchで投げる際に、mode: "cors"を指定します。(下記参照)

データの受け渡し部分はどうやって書くの?

やっとここまで来ました。

frontend
const onClickHandler = async () => {
    const response = await fetch(URL, {
        mode: "cors",
        method: "post",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({name: name}) // 1 フロントエンドから送信するデータ
    })
    const json = await response.json() // 3 バックエンドから受信したデータ
    console.log(json["greeting"])
}
backend
from flask import Flask, request

@app.route('/', methods=['POST'])
def index():
    data = request.json.get('name') # 2 フロントエンドから受信したデータ
    return {"greeting": "Hello! {}".format(name)}

以上です

Reactの勉強をするのが目的だったのですが、ここまで来るだけで大変でした。
引き続き頑張ります。

新規登録して、もっと便利にQiitaを使ってみよう

  1. あなたにマッチした記事をお届けします
  2. 便利な情報をあとで効率的に読み返せます
ログインすると使える機能について
25