メインコンテンツにスキップ
バージョン: 6.x

MobX State Treeとの統合

注記

このガイドは未完成です。プルリクエストを送信して、改善にご協力ください。

このガイドでは、状態管理にMobX State Tree(MST)を使用するReact NativeプロジェクトでReact Navigationを使用するための可能な方法を探ります。このガイドには、サンプルアプリが付属しています。ガイドの一部は、MobXのユーザーにも関連する可能性がありますが、MobXには状態を(逆)シリアル化するための組み込みソリューションがないことに注意してください。

注記

このガイドでは、Mobx State Treeはナビゲーション状態自体を管理するために使用されておらず、ナビゲーションパラメータのみを管理していることに注意してください。

概要

このガイドの目標は、MSTをReact Navigationで使用し、最適な開発者エクスペリエンスを実現することです。このガイドの範囲内では、これは完全なJSリロードを実行し、リロードが発生する前の状態に戻ることができるようにすることを意味します。

これは、React Navigationの組み込みメカニズムを使用して、ナビゲーション状態を永続化することで行います。また、アプリの状態とナビゲーションパラメータも永続化する必要があります。そうすることで、アプリの画面で作業中に完全なJSリロードを実行した場合、同じデータが同じ画面に表示された状態で戻ることができます。

ガイド

まず、初期ナビゲーション構造とReactコンポーネントを作成することから始めます。それが完了したら、MSTで状態のモデリングを続けます。これについて詳しく知りたい場合は、egghead.ioコースを確認してください。

この時点で、MSTオブジェクトをコンポーネントに接続する方法が気になるでしょう。答えは、MobX(MSTでも動作します)用のReactバインディングを含むmobx-reactパッケージにあります。Providerコンポーネントとinjectおよびobserver関数を使用する可能性が高いでしょう。

Providerを使用して、ルートコンポーネントのレンダーメソッドから返すものをラップします。

<Provider myObject={this.myObject}>
<NavigationContainer>{/* Screen configuration */}</NavigationContainer>
</Provider>

これにより、inject関数を介してアプリケーション内の任意のReactコンポーネントからmyObjectにアクセスできるようになり、非常に役立ちます。

observer関数を使用して、observableデータをレンダリングするすべてのコンポーネントをラップします。これにより、レンダリングするデータが変更されると、コンポーネントが再レンダリングされるようになります。

アプリケーション内の画面は、多くの場合、パラメータに依存します。React Navigationでは、ある画面から別の画面にパラメータを送信できます。これらのパラメータはナビゲーション状態に保存されます。ただし、ナビゲーション状態を永続化するには、シリアル化可能である必要があります。MSTオブジェクトは複雑なオブジェクトであり、React Navigationはそれらを(逆)シリアル化する方法を知らないため、この要件はMSTとうまく機能しません。このガイドでは、ナビゲーションパラメータを独自に保存することで、この問題を回避します。

つまり、ある画面から別の画面にパラメータを送信する(例:props.navigation.navigate('MyScreen', { complexMSTObject }))のではなく、パラメータをナビゲーションストアに保存し、パラメータを送信せずにナビゲートし、ターゲット画面でナビゲーションストアからパラメータを取得します。

例を挙げると、ナビゲーションストアは次のようになります。

import { types, onSnapshot, getRoot } from 'mobx-state-tree';
import { Product } from '../models/Product';
import { User } from '../models/User';

export const NavigationStore = types
.model('NavigationStore', {
productDetailScreenParams: types.map(
types.model('ProductDetailScreenParams', {
product: types.optional(types.safeReference(Product)),
})
),
userProfileScreenParams: types.model('UserProfileScreenParams', {
user: types.maybe(types.safeReference(User)),
}),
})
.actions(self => ({
...
}));

userProfileScreenParamsuserエントリを持つ単純なモデルであるのに対し、productDetailScreenParamsProductDetailScreenParamsモデルのマップであることに注意してください。このデータの形状を選択した理由は、アプリに1つのユーザープロファイル画面しかなく、userProfileScreenParamsからパラメーターを読み取るためです。productDetailScreenParamsは、アプリがスタックに複数の製品画面を持つことができるため、マップです。各画面は、マップに保存されたProductインスタンスを指します。マップへのキーは、React Navigationキーです。keyはルートの識別子と考えてください。

ナビゲーションストアは、各画面(製品画面であろうとユーザープロファイル画面であろうと)について、ナビゲーションパラメータを保存する1つのマップである場合もあります。これは、サンプルアプリで採用されているアプローチです。

まとめ

  • React NativeアプリでMobX State TreeとともにReact Navigationを使用できます。
  • Providerコンポーネントとinjectおよびobserver関数を使用して、MobXまたはMSTをReactに接続します。
  • アプリケーション全体の状態を永続化し、JSリロード時に復元することができます。