React Native(Expo) + Djangoでスマホアプリ化しようとした際に詰まった事

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

最近Djangoを使ってWebアプリケーション構築の仕方について理解を進めています。また、DjangoとReact Native(Expo)を使うことでなんとスマホのアプリにも対応させることが出来るらしいということで、絶賛勉強していたのですが、その過程で初歩的ではあるものの詰まった部分があるので、備忘録として残しておこうと思います。

# 参考サイト
DjangoとReact Nativeをどのように連携させるのか比較的簡単に書いていたので、以下サイトを大いに参考にしてやっておりました。
今後、これを使ってどうやって連携させたのかという記事をQiitaに落としておきます。

https://medium.com/@arpitnearlearn/building-a-react-native-mobile-app-with-a-python-django-api-1ee497688e9

# 構築環境
私の構築環境は以下となります。
※あくまでイメージであるという点と、React NativeやAndroid Studio回りは勉強し始めて数日レベルなので、諸々間違っているかもしれません。ご了承ください。
ホストOSはWin11 homeの一般的なものです。その上にanacondaを使用してDjango環境を構築しています。また、NVSを使ってNode.js/React Native/Expoを使用できるようにしています。ExpoからAndroid Studioを呼び出してAndroidスマホをエミュレートしています。
![django-ページ14.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/16fc9d17-7bd4-45d2-730e-f43bfa1b7b52.png)

# 今回問題となったこと。
参考サイトを使ってDjangoとReact Native(Expo(≒Android))を連携させる方法を学んでいました。
基本的にはDjangoにAPIを用意して、スマホアプリはそのAPIを叩きに行くことで連携するようなイメージなのかと考えております。開発環境では全部ローカル環境にて実装しており、非常にわかりにくいですが、本来であれば以下のような形になるのかと・・・
Djangoで作成したWebアプリケーションに対してAPIを作成。一方でスマホ側ではReact Native(Expo)を使ってDjangoが稼働しているサーバのAPIを叩きに行く。こうすることでWebアプリケーションとスマホアプリケーションで同じデータを確認することが出来ると。そういうことなのかなと現状理解しています。
![django-ページ15.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/60eebdeb-f355-4238-1237-7b2d3ec1c111.png)

今回発生した問題は、Expoを使ってPC上にAndroidスマホをエミュレートして、エミュレートしたスマホ内に既にインストールされているExpo goを使ってAPIを叩きに行けているかを確認していたのですが、以下のようなエラーが発生してしまってましたことです。
Expo goにて"Something went wrong"という記載があること。その詳細をView error logで追ってみると"Uncaught Error:java.net.ConnectException: Failed to Connect to /192.168.2.135:8081"という接続エラーが出力されていました。
![AD03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/30e1a20a-23bc-cd87-28ee-cd71ab420156.png)
また、expoコマンドの方でも以下のようなログが見えておりました。今回はAPIを叩きに行くのにAxios（アクシオス）というJavaScriptやTypeScriptでHTTPリクエストを行うためのライブラリを使っているのですが、そいつがNetwork Errorをはいているという状態でした。
![AD04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/1b3ce00a-0c66-ef0b-06bd-48a4a33c82ab.png)
さらに、Djangoはすでにrunserverをしており、PCからはhttp\://localhost:8000で接続できるような状態でありました。
```
PS C:\Users\ohtsu\Documents\DjangoEnv\django-dev\mobilePJ> python manage.py runserver 0.0.0.0:8000
Watching for file changes with StatReloader
Performing system checks...


You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
December 23, 2023 - 14:36:58
Django version 4.1, using settings 'mobilePJ.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CTRL-BREAK.
```
# 原因と対策
今回参考にしていたサイトではReact Native(Expo)で用意したアプリのApp.jsのファイルでaxios.getを以下のようにしてと記載があり、それを踏襲しておりました。
この"http\://localhost"のlocalhostの記載がまずかったです。
```App.js
  useEffect(() => {
    axios.get('http://localhost:8000/api/hello/')
      .then(response => {
        setMessage(response.data.message);
      })
      .catch(error => {
        console.log(error); 
      });
  }, []);
```
私はてっきり同じPC上でDjangoもAndroidも稼働させているので同じIPアドレス(≒localhost)で接続できるとばかり思っていました。ただAndroidのNetworkの設定を見てみると以下のように全く異なったIPアドレスが降られておりました。ネットワークがそもそも違います。
![AD05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/ca09e388-30a8-fcf5-77eb-798ca9746f71.png)
つまり以下のような状態だったということになると思っています。
App.jsでlocalhostと記載されていることで、そのApp.jsファイルを引き渡されたAndroid君は「ん？自分に問い合わせろってこと？」と誤解してしまい、Djangoとうまく通信が出来なかった。ゆえにエラーが発生してしまったと。。。
![django-ページ16.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/b017a718-b99e-926c-4b8d-a2b431fcf828.png)
これを解消するためにApp.jsを修正しました。具体的にはDjangoにアクセスするためのIPアドレスを直書きしました。ポートはDjangoで接続を許可しているポートを設定します。
```App.js
  useEffect(() => {
    axios.get('http://192.168.2.135:8000/api/hello')
      .then(response => {
        setMessage(response.data.message);
      })
      .catch(error => {
        console.log(error); 
      });
  }, []);
```
こうすることでDjangoとExpoで連携できました。
![AD07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/627343b5-8ea6-7815-2abd-838a984c7de5.png)


# 余談
上手く接続できない場合AndroidのExpo goアプリを立ち上げなおし、そのあと手動でexp\://から始まるやつを手動で入力してみて、連携できるかを確認してみるといいかもしれません。
![AD06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/58e3c962-dbff-ad86-67eb-b4a6d01faf8e.png)