🫑

ExpoでFirestoreの値を表示する(iOS)

2024/12/11に公開1

ExpoでCloud Firestoreを使ってみたい

ExpoでFirebaseを使ってみようと思ったがネットの情報がこれで良いのかなと思うものばかりだった。私はbunで環境構築してるのでちょっと特殊ですね。npmでやるとスピードが遅くて😅

Firebaseと接続する手順は普通のReactと似ているようで異なる😅
https://docs.expo.dev/guides/using-firebase/
https://rnfirebase.io/

最初はiOSディレクトリが存在しなかったが専用のコマンドを打つと生成された!
まずはやってみよう。動くものを作るのが先だ。

Firebaseにプロジェクトを作成する。





テストモードで構築してマスターデータを入れておく。





API KEYを取得してコピーして後で貼り付ける


firebaseConfig.tsを作成して先ほどコピーしたAPI KEYを貼り付ける。

firebaseConfig.ts
// Import the functions you need from the SDKs you need
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
export const firebaseConfig = {
  apiKey: "************************",
  authDomain: ""************************",",
  projectId: ""************************",",
  storageBucket: ""************************",",
  messagingSenderId: ""************************",",
  appId: ""************************","
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);

App.tsxにCloud Firestoreから取得するデータを表示するコードを書く。

App.tsx
import { useEffect, useState } from 'react';
import { StyleSheet, Text, View, ScrollView, ActivityIndicator } from 'react-native';
import { initializeApp } from 'firebase/app';
import { getFirestore, collection, getDocs } from 'firebase/firestore';
import { firebaseConfig } from './firebaseConfig';

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);

interface User {
  id: string;
  name: string;
}

export default function App() {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let isMounted = true;

    const fetchUsers = async () => {
      try {
        console.log('Fetching users...');
        const querySnapshot = await getDocs(collection(db, 'users'));
        console.log('QuerySnapshot:', querySnapshot.size, 'documents found');
        
        if (isMounted) {
          const userList = querySnapshot.docs.map(doc => {
            const data = doc.data();
            console.log('Document data:', { id: doc.id, data });
            return {
              id: doc.id,
              name: data.name || ''
            };
          });
          console.log('Processed user list:', userList);
          setUsers(userList);
        }
      } catch (err) {
        console.error('Error details:', err);
        if (isMounted) {
          setError('データの取得に失敗しました');
        }
      } finally {
        if (isMounted) {
          setLoading(false);
        }
      }
    };

    fetchUsers();

    return () => {
      isMounted = false;
    };
  }, []);

  if (loading) {
    return (
      <View style={styles.centerContainer}>
        <ActivityIndicator size="large" color="#0000ff" />
      </View>
    );
  }

  if (error) {
    return (
      <View style={styles.centerContainer}>
        <Text style={styles.errorText}>{error}</Text>
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>ユーザー一覧</Text>
      {users.length === 0 ? (
        <View style={styles.centerContainer}>
          <Text style={styles.noData}>ユーザーデータがありません</Text>
          <Text style={styles.subText}>Firestoreのusersコレクションにデータを追加してください</Text>
        </View>
      ) : (
        <ScrollView style={styles.scrollView}>
          {users.map((user) => (
            <View key={user.id} style={styles.userCard}>
              <Text style={styles.userName}>{user.name}</Text>
            </View>
          ))}
        </ScrollView>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    padding: 20,
    paddingTop: 50,
  },
  centerContainer: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  scrollView: {
    flex: 1,
  },
  userCard: {
    padding: 15,
    marginBottom: 10,
    backgroundColor: '#f5f5f5',
    borderRadius: 8,
  },
  userName: {
    fontSize: 16,
  },
  errorText: {
    color: 'red',
    fontSize: 16,
  },
  noData: {
    fontSize: 18,
    color: '#666',
    marginBottom: 10,
  },
  subText: {
    fontSize: 14,
    color: '#999',
  },
});

専用のコマンドでビルドするが最初は長い😅
ビルドできたら設定画面のようなものが出てくる。ここアプリの画面じゃないのかなってメニューをタップするとアプリの画面が開く。

bun x expo run:ios

iOS環境構築手順書

結構詰まったのでやり方を書いておく。もしかしたら人によってはうまくいかないかもしれない😱

プロジェクトを作成する。

bunx create-expo-app expo-firedemo -t expo-template-blank-typescript

前提条件

  • macOS
  • Xcode がインストール済み
  • bun がインストール済み

1. プロジェクトの初期設定

1.1 必要なパッケージのインストール

# Firebaseとその他必要なパッケージをインストール
bun add firebase @expo/webpack-config expo-dev-client

# Expoのビルドプロパティ設定用パッケージをインストール
bun add expo-build-properties

1.2 Firebase設定

  1. Firebase Consoleでプロジェクトを作成
  2. Webアプリを追加し、設定情報を取得
  3. firebaseConfig.ts を作成し、設定を追加
export const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
  appId: "YOUR_APP_ID"
};

1.3 app.json の設定

{
  "expo": {
    // ... 他の設定 ...
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.yourcompany.yourapp"
    },
    "plugins": [
      ["expo-build-properties", {
        "ios": {
          "useFrameworks": "static"
        }
      }]
    ]
  }
}

2. ビルドコマンド

2.1 開発ビルドの作成

bun x expo prebuild

このコマンドは以下の処理を行います:

  • iOSネイティブプロジェクトの生成
  • 必要な依存関係の設定
  • CocoaPodsの初期設定

2.2 iOSシミュレータでの実行

bun x expo run:ios

このコマンドは以下の処理を実行します:

  1. ネイティブコードのビルド(初回は10-15分程度かかります)
  2. JavaScriptバンドルの作成
  3. アプリのコンパイルと署名
  4. シミュレータへのインストールと起動

2.3 開発サーバーの起動

bun start

このコマンドは開発サーバーを起動し、以下の機能を提供します:

  • ホットリロード
  • デバッグ情報の表示
  • コンソールログの表示

3. トラブルシューティング

3.1 ビルドエラーが発生した場合

# iOSビルドファイルの削除
rm -rf ios/

# node_modulesの削除
rm -rf node_modules/
rm -rf package-lock.json
rm -rf yarn.lock
rm -rf bun.lockb

# 依存関係の再インストール
bun install

# プロジェクトの再ビルド
bun x expo prebuild
bun x expo run:ios

3.2 Metro Bundlerのキャッシュクリア

bun x expo start --clear

4. 注意点

  1. 初回ビルドは時間がかかります(10-15分程度)
  2. 2回目以降のビルドは比較的短時間で完了します(1-2分程度)
  3. Firebaseの設定は正確に行う必要があります
  4. シミュレータの起動には十分なメモリが必要です

5. 開発フロー

  1. コード変更
  2. 変更の保存
  3. シミュレータで自動リロード
  4. コンソールログで動作確認
  5. 必要に応じてビルドの再実行

6. デバッグ

  1. コンソールログの確認: アプリ実行中にログが表示されます
  2. React Native Debugger: Chrome/Edge開発者ツールで確認可能
  3. Metro logs: ターミナルで確認可能

Discussion