Django × Reactでハイブリッド株式管理アプリを構築する【株価情報表示編】

今回は、前回作成したHome.tsx に現在登録している株価情報を表示する処理を作成していきます。

# URLパターン設定
```py:equity_hub/urls.py
urlpatterns = [
    path('home/', views.react_view, name='home'),
    path('home/api/', views.EquityHubHomeViewAPI.as_view(), name='home_api'),
```

# Serializer の作成
Django から React には データを Json形式に変換して渡す必要があります。
事前に serializers.py ファイルを作成して変換できるようしておきます。
```py:serializers.py
from rest_framework import serializers
from .models import EquityHub

class EquityHubSerializer(serializers.ModelSerializer):
    class Meta:
        model = EquityHub
        fields = '__all__'
```

# Viewの設定
Django で登録されている登録されている株価情報を取得するViewを作成します。
```py:equity_hub/views.py
from .serializers import EquityHubSerializer

@method_decorator(login_required, name='dispatch')
class EquityHubHomeViewAPI(APIView):
    def get(self, request, *args, **kwargs):
        serializer = EquityHubSerializer(EquityHub.objects.filter(user=self.request.user), many=True)
        return Response(serializer.data)
```
Response で React に返す際は、作成しておいた EquityHubSerializer で Json形式に変換して返す必要があります。

# React からの呼び出し
今回は、Home.tsxに直接関数を書かずに、API専用のapiService.tsx を作成していきます。
※この辺りは好みがわかれると思うの好きに配置してください。
先にHome.tsx側の準備
```tsx:react-frontend/src/pages/home/Home.tsx
import React, { useEffect, useState } from 'react';
import { fetchEquityHubs } from '../apiService';

interface EquityHub {
    stock_No: number;
    symbol: string;
    name: string;
    dividend_yield: number;
    price: number;
    shares_owned: number;
}

const StockHoldings = () => {
  const [equityHubs, setEquityHubs] = useState<EquityHub[]>([]);

  // 株価データを取得
  useEffect(() => {
    fetchEquityHubs(setEquityHubs);
  }, []);
```
ホーム画面ロード時に1回だけ読み込むように useEffectを設定

API専用ファイル
```tsx:react-frontend/src/pages/apiService.tsx
import axios from 'axios';

// 初期データを取得する関数
export const fetchEquityHubs = async (setEquityHubs: React.Dispatch<React.SetStateAction<any[]>>) => {
  try {
      const response = await axios.get<any[]>('/home/api/'); // APIエンドポイントを指定
      setEquityHubs(response.data);
  } catch (error) {
      console.error('Error fetching data:', error);
  }
};
```
await axios.get('/home/api/') で 登録済みデータを取得してsetEquityHubs で設定することでHome.tsx 内で equityHubs として値を使用可。

# 取得した株価情報の表示
```tsx:react-frontend/src/pages/home/Home.tsx
 {equityHubs.map((content) => {
          return (
            <ul className="list-group list-group-horizontal" key={content.stock_No}>
              <li className="list-group-item col" style={{ flex: '2' }} >{content.name}({content.symbol})</li> {/*銘柄名(コード) */}
              ...
```
以降はデータの表現方法になるので省略します。
好きなように表示してみてください。

# React で build 実行
```sh
cd react-frontend

npx webpack
```

# 確認
```sh
cd ../

python manage.py runserver
```
http://127.0.0.1:8000/home/ にアクセスして下記のように項目が表示されれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517045/2104d7a9-2b29-b42e-07ab-df65588b5aa4.png)


# 終わりに
これにて株式の登録/更新/削除から表示までができるようになりました。
今回作成して難しかった点は、Reactを使用する際に今回作成したreact-base.html内の`<div id="root"></div>`部分を再レンダリングしていくイメージがなかったので最初混乱していました。
また、ちょっとした調整でもReactを毎回buildしなければならないのは手間に感じました。
※AWS CI/CD でどうにかできないか考えてみます。

今後の拡張としては、登録している株式情報をAWS BedRockに渡して評価してもらった結果を表示する機能の追加を考えています