ポートフォリオサイトのロゴ
Icon for React + Flaskを連携させてみる

React + Flaskを連携させてみる

ReactとFlaskを連携させたアプリケーション開発の手順。

目的

ReactとFlaskを使用したアプリケーションを作りたい。
そのまえに一度連携させて色々反映させてみる。

フロー

Projectの作成

ディレクトリ構成はフロントエンドとバックエンドで分けることにしました。
参考記事→https://qiita.com/mihonak/items/91ac9c068831c0a3bb88

もろもろ起動させる

フロントエンド側ではcreate-react-appでプロジェクトを作成し、動くか確認してみます。
image.png

いつ見てもかっこいいですよね

バックエンド側でもFlaskの公式ドキュメントからソースコードを引用して動かしてみます。
公式ドキュメント→https://msiz07-flask-docs-ja.readthedocs.io/ja/latest/quickstart.html#a-minimal-application

image.png

エンドポイントの作成

Python側から返すデータとして適当な値を考えます。

from flask import Flask, jsonify
 
app = Flask(__name__)
 
@app.route('/api/data', methods=['GET'])
def get_data():
    data = {'name': 'tarou', 'age': 30, 'job': 'developer'}
    return jsonify(data)
 
if __name__ == '__main__':
    app.run(debug=True)

Reactの作成

エンドポイントからデータを取得し、表示するアプリケーションを作成します。

import { useEffect, useState } from 'react';
import './App.css';
import axios from "axios";
 
interface Data {
  name: string;
  age: number;
  job: string;
}
 
function App() {
  const [data, setData] = useState<Data | null>(null);
 
  useEffect(() => {
    axios.get('http://127.0.0.1:5000/api/data')
      .then((response) => setData(response.data))
      .catch((error) => console.error(error));
  }, []);
 
  return (
    <div className="App">
      <header className="App-header">
        <div>
          {data && (
            <div>
              <p>Name: {data.name}</p>
              <p>Age: {data.age}</p>
              <p>Job: {data.job}</p>
            </div>
          )}
        </div>
      </header>
    </div>
  );
}
 
export default App;

この時点では何も表示されていません。
image.png

プロキシの設定

調べてもなんとなくしか分からなかったのでChatGPTに��いてみた。

プロキシの設定: このステップはReactとFlaskが同じマシン上の異なるポートで動作するときに重要です。
例えば、Reactは通常ポート3000で、Flaskはポート5000で動作します。
 
異なるポートから来るリクエストは、セキュリティ上の理由からウェブブラウザによってブロックされる可能性があるため、これは問題となります。
 
これを解決する方法の1つは、CORS (Cross-Origin Resource Sharing)を設定することですが、これは複雑でエラーが発生しやすいです。
 
その代わりに、Reactの開発サーバーにプロキシを設定することが推奨されます。
これは、Reactの開発サーバーがFlaskのサーバーに直接リクエストを転送するようにすることです。
これにより、Reactアプリケーションは自分自身が動作しているポート(通常は3000)からリクエストを送り、これがプロキシによってFlaskのポート(通常は5000)に転送されます。
結果として、ウェブブラウザはこのリクエストを同一オリジンからのものとして扱い、問題なくリクエストを許可します。
 
このプロキシを設定するには、Reactアプリケーションのpackage.jsonファイルにproxyフィールドを追加します。

異なるポートからくる通信はセキュリティの観点でブロックされるらしい。
React推奨のやり方で試してみる。

{
  "proxy": "http://127.0.0.1:5000",
}

その後すこしソースコードを修正し、無事反映されました。

React
import { useEffect, useState } from 'react';
import './App.css';
import axios from "axios";
 
interface Data {
  name: string;
  age: number;
  job: string;
}
 
function App() {
  const [data, setData] = useState<Data | null>(null);
 
  useEffect(() => {
    axios.get('http://127.0.0.1:5000/api/data')
      .then((response) => {setData(response.data)})
      .catch((error) => console.error(error));
  }, []);
 
  return (
    <div className="App">
      <header className="App-header">
        <div>
          {data && (
            <div>
              <p>Name: {data.name}</p>
              <p>Age: {data.age}</p>
              <p>Job: {data.job}</p>
            </div>
          )}
        </div>
      </header>
    </div>
  );
}
 
export default App;
Flask
from flask import Flask, jsonify
 
app = Flask(__name__)
 
@app.route('/', methods=['GET'])
def hello():
    return '<p>Hello World</p>'
 
@app.route('/api/data', methods=['GET'])
def get_data():
    data = {'name': 'tarou', 'age': 30, 'job': 'developer'}
    return jsonify(data)
 
if __name__ == '__main__':
    app.run()

image.png