チュートリアル: Atlas Device Sync for React Native
項目一覧
完了までの推定時間: 30分(React Native の経験により異なります)
RealmReact Native SDKと @realm/React を使用できます でモバイルReact Native アプリケーションを構築できます。このチュートリアルでは、Flexible Sync を使用する独自のアプリを構築する方法について説明しています。
このチュートリアルでは、事前に構築された TypeScript テンプレート アプリケーションから始めて、すべてがどのように組み合わされるかについて説明しています。
このアプリは、動作する React Native アプリケーション(フロントエンド)とそれに対応する App Services App 構成ファイル(バックエンド)を含む事前構築済みのテンプレートです。
テンプレート アプリは、ユーザーがタスクを管理するためにさまざまなことを行うことができる To Do リストの基本アプリケーションです。
電子メール/パスワード アカウントを作成し、アプリにログインまたはログアウトします。
自分のタスクを作成、読み取り、更新、削除します。
ユーザーが所有者でない場合でも、すべてのタスクを表示します。
テンプレート アプリを実行したら、既存のItem
モデルに新しい priority
フィールドを追加し、Flexible Sync サブスクリプションを更新して、優先度の範囲内のアイテムのみを表示します。この例では、テンプレート アプリを独自のニーズに合わせて調整する方法について説明しています。テンプレート アプリの現在の構造を考慮すると、必ずしもこの変更を行う必要はありません。
テンプレートアプリには、デバイスがオフラインモードになっていることをシミュレートするトグルが用意されています。このトグルを使用すると、Device Sync 機能を素早くテストして、インターネットに接続していないユーザーをエミュレートできます。ただし、本番アプリケーションでは、ユーザーがこのトグル削除する可能性が高いでしょう。
注意
クイック スタートを確認する
ガイド付きチュートリアルに従うのではなく、自分で調べたい場合は、 React Native クイック スタートを確認できます。コピー可能なコード サンプルと、Atlas Device Sync を使用して React Native アプリを設定するために必要な重要な情報が含まれています。
前提条件
このチュートリアルを開始する前に、React Native 開発用のローカル環境を設定する必要があります。手順について詳しくは、React Native ドキュメントの「 開発環境の設定」セクションを参照してください。
このチュートリアルは、テンプレート アプリから始めます。 テンプレート アプリを作成するには、 Atlas アカウント、 API キー、 App Services CLI が必要です。
Atlas アカウントの作成の詳細については、「 Atlas の使用開始」ドキュメントを参照してください。 このチュートリアルでは、無料階層クラスターを持つ Atlas アカウントが必要です。
ログインする MongoDB Cloud アカウントの Atlas API キーも必要です。 App Services CLI を使用してテンプレート アプリを作成するには、プロジェクト オーナーである必要があります。
App Services CLI のインストールについて詳しくは、「 App Services CLI のインストール」を参照してください。 インストール後、Atlas プロジェクトの API キーを使用して「 login 」コマンドを実行します。
テンプレート アプリを使用する
このチュートリアルは、 react-native.todo.flex
という名前の React Native SDK Flexible Sync テンプレート アプリを基本にして作成されており、デフォルトのアプリから始めて、新しい機能について説明しています。
テンプレート アプリの詳細については、「テンプレート アプリ 」を参照してください。
Atlas アカウントがまだない場合は、テンプレート アプリを配置するためにサインアップしてください。
「App Services App」ガイドに記載されている手順に従い、 Create App from Templateを選択します。Real-time Sync テンプレートを選択します。これにより、Device Sync テンプレート App Services App クライアントの 1 つで使用するために事前構成された App Services App が作成されます。
テンプレート アプリを作成すると、UI に Get the Front-end Code for your Template というラベルの付いたモーダルが表示されます。このモーダルには、テンプレート アプリのクライアントコードを .zip
ファイルとしてダウンロードする方法や、App Services CLI を使用してクライアントを取得する方法が表示されます。
.zip
または App Services CLI メソッドを選択した後、画面の指示に従ってクライアント コードを取得します。このチュートリアルでは、JavaScript (React Native) クライアント コードを選択します。
注意
デフォルトの Windows ZIP ユーティリティで、.zip ファイルが空白ファイルとして表示される。この問題が発生した場合は、利用可能なサードパーティの zip プログラムのいずれかを使用してください。
appservices apps create コマンドでバックエンドを設定し、React Native テンプレート アプリを作成してこのチュートリアルのベースとして使用します。
ターミナル ウィンドウで次のコマンドを実行して、「Myチュートリアル App」という名前のアプリを作成し、環境が「開発」(本番環境やQAではなく)に設定されているUS-VA
リージョンに配置されます。
appservices app create \ --name MyTutorialApp \ --template react-native.todo.flex \ --deployment-model global \ --environment development
このコマンドは、 --name
フラグの値と同じ名前で現在のパスに新しいディレクトリを作成します。
Device Sync クライアントコードを含む Github リポジトリをフォークしてクローンできます。React Native クライアント コードは https://github.com/mongodb/template-app-react-native-todo で入手できます。
このプロセスを使用してクライアントのコードを取得する場合は、クライアントで使用するテンプレート アプリを作成する必要があります。 「テンプレート アプリの作成」 の手順に従って、Atlas App Services UI、App Services CLI、または管理 API を使用して Device Sync テンプレート アプリを作成します。
テンプレート アプリの設定
テンプレート アプリをコンピューター上で起動して実行するには、次の手順に従います。
依存関係のインストール
ターミナルで、クライアント・コードのあるディレクトリに移動します。App Services CLI を使用してアプリを作成した場合は、 MyTutorialApp/react-native.todo.flex
に進みます。そうでない場合は、ダウンロードまたはクローンしたプロジェクトのルートに移動します。次に、次のコマンドを実行して、アプリの依存関係のインストールに移動します。
npm install
iOS デバイスまたはシミュレーターでアプリをビルドして実行するには、 CocoaPods を使用して追加の iOS 依存関係をインストールします。
cd ios npx pod-install
アプリをビルドする
この時点で、iOS、Android、またはその両方で実行できる、完全に機能する React Native アプリが完成しているはずです。
エラーが発生した場合やその他の問題が発生した場合は、React Native 環境が正しく設定されていることを確認してください。公式の「React Native 開発環境のセットアップ」ガイドを参照してください。開発 OS とターゲット OS のすべての手順に従います。
すべての機能が iOS で動作することを確認するには、アプリをビルドして iOS シミュレーターで実行します。
npm run ios
以下の方法で、すべての機能が Android で動作するか確認できます。
Android エミュレータを起動します。詳しい方法については、「Android Emulator でのアプリの実行」を参照してください。
エミュレータでアプリをビルドします。
npm run android Error: spawn ./gradlew EACCES
はよくあるエラーの 1 つで、プロジェクト ファイルのアクセス権限が適切ではないことを意味します。MacOS でこのエラーを修正するには、ターミナルにchmod 755 android/gradlew
と入力します。
アプリをテストする
ビルドが完了すると、シミュレーター上で機能するアプリが実行されるはずです。アプリで、新しいアカウントを登録して、機能をテストします。
いくつかの To Do アイテムをリストに追加します。
1 つまたは 2 つのアイテムのチェックボックスをオンにして、「完了」としてマークします。
アイテムの上でXを押すと、そのアイテムがリストから削除されます。
アプリ内でインターネット接続を切り替えて、オフライン モードをシミュレートします。
Atlas クラスターに接続してtodo.Item
コレクションをクエリすると、アプリのデータを表示できます。React Native アプリがオフライン モードでない限り、アプリ内の新しいデータと変更は自動的にtodo.Item
コレクションに同期されます。
Tip
Atlas Cluster に接続する方法については、「クラスターへの接続」を参照してください。
同様に、コレクション内のすべての変更は React Native アプリに自動的に同期されます。クラスター内のアイテムの完了ステータスを変更してみてください。React Nativeアプリは、ネットワーク接続が利用可能になるたびに、新しい値で自動的に更新されます。
Tip
クラスター内のデータの更新について詳しくは、「ドキュメントの更新」を参照してください。
テンプレートアプリに慣れる
テンプレート アプリが実行できたので、コードを調べて、何を扱っているか確認してみましょう。
Atlas App Services App
テンプレート アプリには、 backend
ディレクトリに完全に構成された App Services Appが含まれています。クライアント アプリケーションが接続に使用するatlasConfig.json
内のユニークな appId
値があります。
また、次の事前定義された構成も含まれています。
Atlas Cluster にリンクされたデータソース。
React Native アプリの
Item
クラスに一致するtodo.Item
コレクションのデータ モデル。ユーザーがメールとパスワードを使用してアプリに登録し、ログインできるようにする認証プロバイダ。
1 つのセッションロールによる柔軟な同期構成により、ユーザーは自分のアイテムの読み取りと書込みを行ったり、他のユーザーのアイテムを表示したりできます。
React Native アプリ
React Native アプリは、iOS および Android デバイスで実行できる完全に構成されたモバイル クライアントです。
このアプリでは、@realm/react ライブラリが使用されます。このライブラリには、Atlas バックエンドと Realm データベースの操作を効率化する React フックとコンポーネントが含まれています。
アプリにはいくつかの構成ファイルとディレクトリが含まれていますが、アプリをカスタマイズする場合を除き、それらは無視できます。このチュートリアルでは、 source/
ディレクトリ内の React コンポーネントについて理解している必要があります。
ファイル名 | 説明 |
---|---|
ItemSchema.tsx | Item クラス(オブジェクト データモデルを含む)。このクラスを AppWrapper.tsx にインポートして、アプリ全体の Realm スキーマに含めます。 |
AppWrapper.tsx | これは、アプリのルート コンポーネントです。これはラッパー コンポーネントとして機能し、すべての @realm/react プロバイダーが含まれます。ここで、Realm と Atlas バックエンドへの接続を構成します。 |
App.tsx | アプリの機能のほとんどは、このコンポーネントとその子に含まれています。 @realm/react プロバイダーがこのコンポーネントをラップしているため、Atlas バックエンドのインスタンス、ユーザー オブジェクトにアクセスし、Realm データベースと対話することができます。 |
WelcomeView.tsx | ユーザーが最初にアプリを開いたときに表示されるユーザー登録とログイン フォーム。 |
ItemListView.tsx | ユーザーがログイン後に操作するメインの ToDo リスト アプリ。 Item Realm オブジェクトを照会し、リストに表示します。また、新しい Item オブジェクトを作成して Realm に保存するコードも含まれています。 |
CreateToDoPrompt.tsx | 新しい Item オブジェクトのデータを入力できる UI フォーム。実際に新しいオブジェクトを生成するコードは ItemListView.tsx にあります。 |
LogoutButton.tsx | 認証されたユーザーをログアウトする再利用可能なボタン。 |
OfflineModeButton.tsx | 現在の Realm syncSession を一時停止および再開することでオフライン モードをシミュレートする再利用可能なボタン。 |
優先度レベルフィールドを追加する
テンプレート アプリにすでに用意されている機能について理解できたので、新しい機能を実装するコードを記述してみましょう。
このチュートリアルでは、 Item
オブジェクトに新しい priority
プロパティを追加します。これにより、ToDo を重要度別に整理し、最も重要なものにのみ集中できるようになります。
優先順位を定義する
少数の名前付き優先レベルを許可し、レベルを簡単に並べ替えられるようにしたいと考えています。そのために、ヘルパー関数を使用して enum
オブジェクトを定義します。このオブジェクトは、順序付けられたレベル名のセットを、優先順位を表す整数にマッピングしたり、レベル名から割り当てたりします。
source/ItemSchema.tsx
のインポート ステートメントの直下に次のコードを追加します。
function createEnum(arr) { arr.forEach((p, i) => arr[p] = i); return arr; } // Priority.High === 1 // Priority[Priority.High] === "High" export const Priority = createEnum([ "Severe", "High", "Medium", "Low", ])
enum
内の優先度レベルは、最も重要なものから最も重要でないものの順に並べられています。各レベルに対応するインデックス値は、最も重要な Priority[0]
から最も重要でない Priority[3]
まで増加します。つまり、優先度が高いほど(つまり、より重要であるほど)、インデックス値は低くなります。
Item
データモデルを更新する
これで、 priority
フィールドの可能な値を定義する enum
ができました。ただし、 Item
クラスで priority
フィールドを定義する必要があります。
priority
を Item
データ モデルに追加するには、source/ItemSchema.tsx
のコードに次の行を追加します。
export class Item extends Realm.Object<Item> { _id!: BSON.ObjectId; isComplete!: boolean; summary!: string; owner_id!: string; priority!: string; static schema: Realm.ObjectSchema = { name: 'Item', primaryKey: '_id', properties: { // This allows us to automatically generate a unique _id for each Item _id: {type: 'objectId', default: () => new BSON.ObjectId()}, // All todo items will default to incomplete isComplete: {type: 'bool', default: false}, summary: 'string', owner_id: 'string', priority: { // Store the index value of the Priority enum rather than the name type: 'int', default: Priority.High }, }, }; }
注意
同期が壊れなかった理由
この時点で、React Native Item
モデルと App Services App 内の対応するスキーマは一致しなくなります。それで問題ありません。
Realm オブジェクトにプロパティを追加しても重大な変更ではないため、クライアントをリセットする必要はありません。 テンプレート アプリでは開発モードが有効になっているため、クライアント Realm オブジェクトへの変更はサーバー側のスキーマに反映されます。 詳しくは、「開発モードとデータモデルの更新 」を参照してください。
優先度ピッカーを追加する
アプリのデータ モデルには、各 Item
オブジェクトに対して priority
が含まれるようになりました。アプリの UI をアップデートして、新しい To Do をリストに追加するときに優先順位の値を選択できるようにしましょう。
まず、優先順位ピッカー コンポーネントを実装するための外部ライブラリをインストールします。プロジェクト ルート内のターミナルで次のコマンドを実行します。
npm install @react-native-picker/picker
iOS 用にビルドしている場合は、パッケージをインストールした後、関連付けられている Cocoapods をリンクしてください。
npx pod-install
Tip
インストール後にアプリを再ビルドする必要がある場合があります。これを行うには、プロジェクトのバンドラーを停止し、ビルド コマンドを実行します。
npm run ios
npm run android
パッケージが完全にインストールされたので、ピッカーを使用するように新しい To-Do 作成プロンプトコンポーネントを更新しましょう。
source/CreateToDoPrompt.tsx
の先頭に次のインポートを追加します。
import {Picker} from '@react-native-picker/picker'; import {Priority} from './ItemSchema';
次に、 CreateToDoPrompt
コンポーネントを変更します。
onSubmit()
props の定義にpriority
を追加する状態フックで
priority
を追跡するインポートした
Picker
コンポーネントに状態を接続するpriority
をonSubmit()
ハンドラに渡す
type Props = { onSubmit(args: {summary: string; priority: string;}): void; }; export function CreateToDoPrompt(props: Props): React.ReactElement<Props> { const {onSubmit} = props; const [summary, setSummary] = useState(''); const [priority, setPriority] = useState(Priority.High); return ( <View style={styles.modalWrapper}> <Text h4 style={styles.addItemTitle}> Add To-Do Item </Text> <Input placeholder="What do you want to do?" onChangeText={(text: string) => setSummary(text)} autoCompleteType={undefined} /> <Picker style={{width: '80%'}} selectedValue={priority} onValueChange={value => setPriority(value)}> {Priority.map(priority => ( <Picker.Item key={priority} label={priority} value={Priority[priority]} /> ))} </Picker> <Button title="Save" buttonStyle={styles.saveButton} onPress={() => onSubmit({summary, priority})} /> </View> ); }
source/ItemListView.tsx
で、 createItem()
関数を変更して priority
を受け入れて使用します。
const createItem = useCallback( ({summary, priority}: {summary: string, priority: string}) => { realm.write(() => { return new Item(realm, { summary, owner_id: user?.id, priority }); }); }, [realm, user], );
次に、ToDo 送信ハンドラーの作成を変更して、 priority
レベルを受け入れ、それを createItem()
に渡します。
<CreateToDoPrompt onSubmit={({summary, priority}) => { setShowNewItemOverlay(false); createItem({summary, priority}); }} />
最後に、リストアイテムテンプレートを変更して、ToDo の priority
を summary
の前にレンダリングします。
<ListItem key={`${item._id}`} bottomDivider topDivider hasTVPreferredFocus={undefined} tvParallaxProperties={undefined}> <Text>{item.priority}</Text> <ListItem.Title style={styles.itemTitle}> {item.summary} </ListItem.Title> <ListItem.Subtitle style={styles.itemSubtitle}> {item.owner_id === user?.id ? '(mine)' : ''} </ListItem.Subtitle> <ListItem.CheckBox checked={item.isComplete} checkedColor={COLORS.primary} iconType="material" checkedIcon="check-box" uncheckedIcon="check-box-outline-blank" onPress={() => toggleItemIsComplete(item._id)} /> <Button type="clear" onPress={() => deleteItem(item._id)} icon={ <Icon type="material" name="clear" size={12} color="#979797" tvParallaxProperties={undefined} /> } /> </ListItem>
同期サブスクリプションを更新する
デバイス同期プロトコルは、各同期クライアントが標準の RQL クエリを使用してアプリケーション データのサブセットを選択し、そのサブセットに サブスクライブ する柔軟なモデルを使用します。これにより、サブセット内のすべてのデータの最新バージョンが自動的にデバイスに取得され、データの変更がデバイス間で同期されます。
たとえば、使用しているテンプレート アプリには、現在のユーザーが所有するアイテムに対する次の組み込みサブスクリプションがあります。
realm.subscriptions.update(mutableSubs => { mutableSubs.removeByName(itemSubscriptionName); mutableSubs.add( realm.objects(Item).filtered(`owner_id == "${user?.id}"`), {name: ownItemsSubscriptionName}, ); });
アプリが必要とするデータのみを同期するように、実行時にサブスクリプションをカスタマイズできます。その方法を表示する機能を追加しましょう。
このチュートリアルでは、2 つのモードを切り替えることができるボタンを追加します。1 つはアプリがすべての ToDo アイテムを同期するモード、もう 1 つはpriority
が「高」または「重大」の重要なアイテムのみを同期するモードです。
UI にモード トグルを追加する
まず、現在のモードを追跡するために、 ItemListView
コンポーネントに useState()
フックを追加します。
const [showImportantOnly, setShowImportantOnly] = useState(false);
次に、ToDo リストの一番下、 <ListItem>
の後にモードを切り替える新しいボタンを追加します。
<Button title={showImportantOnly ? 'Show All' : 'Show Important Only'} buttonStyle={{ ...styles.addToDoButton, backgroundColor: showImportantOnly ? '#00A35C' : '#FFC010', }} onPress={() => setShowImportantOnly(showImportantOnly => !showImportantOnly)} />
同期サブスクリプションを更新する
この点で、アプリは UI でモードを切り替えることができますが、他に何もしていないため、モードは機能的に同じです。現在のモードに関連するデータのみを同期するようにサブスクリプションをアップデートしましょう。
ItemListView
コンポーネントの最初の useEffect
に、現在のモードをチェックし、showImportantOnly
モードがアクティブな場合はクエリに priority
フィルターを付け加えるコードを追加します。
useEffect(() => { if (showAllItems) { realm.subscriptions.update(mutableSubs => { mutableSubs.removeByName(ownItemsSubscriptionName); mutableSubs.add(realm.objects(Item), {name: itemSubscriptionName}); }); } else if (showImportantOnly) { realm.subscriptions.update(mutableSubs => { mutableSubs.removeByName(itemSubscriptionName); mutableSubs.add( realm.objects(Item).filtered(`owner_id == "${user?.id}" && priority <= 1`), {name: ownItemsSubscriptionName}, ); }); } else { realm.subscriptions.update(mutableSubs => { mutableSubs.removeByName(itemSubscriptionName); mutableSubs.add( realm.objects(Item).filtered(`owner_id == "${user?.id}"`), {name: ownItemsSubscriptionName}, ); }); } }, [realm, user, showAllItems, showImportantOnly]);
重要
useEffect
の 2 番目の引数の依存関係のリストに showImportantOnly
を追加することを忘れないでください。
アプリをテストする
これで、アプリは現在のモードに基づいて同期サブスクリプションを変更するように設定されました。
アプリを再構築して実行し、すべてが動作することを確認します。ToDo アイテムを作成、完了、削除できるほか、すべてのアイテムの表示と重要なアイテムのみの表示を切り替えることもできます。
Tip
開発者モードが有効になっている場合にサブスクリプションを変更する
このチュートリアルでは、サブスクリプションを変更し、優先順位フィールドを初めてクエリすると、フィールドは Device Sync Collection Queryable Fieldsに自動的に追加されます。 これは、テンプレート アプリで開発モードがデフォルトで有効になっているために発生します。 開発モードが有効になっていない場合、クライアント側の同期クエリで使用するには、フィールドをクエリ可能なフィールドとして手動で追加する必要があります。
詳細については、「クエリ可能なフィールド 」を参照してください。
次のステップ
React Native SDK のドキュメントをお読みください。
MongoDB Communityに参加して、他の MongoDB 開発者や技術専門家から学びます。
Triggersと Atlas Search を使用して、テンプレート アプリに機能を追加します。
エンジニアリング プロジェクトと専門家が提供するサンプルプロジェクトを探索します。
注意
フィードバックの共有
ではどのようにGoしましたか。 ページ右下にあるRate this pageウィジェットを使用して、有効性を評価します。 またはGithub リポジトリ に問題を報告する 問題が発生した場合は、。