ReactNativeを備えたMobX、簡略化
状態管理はReactアプリケーションの中核であり、Reactは単なるUIライブラリであるため、アプリの状態を処理するための何かが必要です。 状態管理は面倒になる可能性があり、状態に一貫性がないため、管理しにくいReactアプリケーションを簡単に作成できます。
この記事では、ReactNativeアプリケーションで状態管理ソリューションとしてMobXを使用する方法について学習します。
状態管理とは何ですか?
State は、アプリが処理しているデータにすぎません。 状態は、コンポーネントに必要なデータを保存し、コンポーネントのレンダリング方法に影響を与えます。 状態管理は、そのデータを管理するプロセスです。 特定のアプリでデータを監視および取得することは困難な場合があり、そこで状態管理ライブラリが役に立ちます。 ReduxやReactContext API を使用するなど、状態を管理する方法は複数ありますが、ここではMobXについて説明します。
MobXとは何ですか?
MobX は、任意のJavaScriptフレームワークで使用できる状態管理ライブラリです。 ReactとMobXは一緒に強力であり、完全なフレームワークとして機能します。 MobXは、ReactNativeがコンポーネントのレンダリングに使用するアプリケーションの状態を保存および更新するメカニズムを提供します。 MobXの背後にある哲学は次のとおりです。*「アプリケーションの状態から派生できるものはすべて、派生する必要があります。 自動的。"*
核心概念
派生はMobXのバックボーンを形成し、繰り返される状態を破棄できるようにします。 アイデアは次のとおりです。
最小限の状態(観察可能な状態)を見つけ、すべてを派生させ(派生状態)、状態をそれ以上の状態に変えないでください。
MobXのコアには、 Observables 、 Actions 、およびReactionsという3つの重要な概念があります。 ストアにはこれら3つが含まれており、ReactNativeアプリケーションによって使用されます。
オブザーバブル
MobXのオブザーバブルは、アプリケーションのコア状態を保持する単なるコンテナーです。 アイデアは、オブザーバーが反応できる新しい変化をオブジェクトが放出できるようにすることです。 これは、@observable
デコレータを使用して実現できます。
時間の経過とともに変化するcount
という名前の変数があるとします。 次の方法で簡単に観察できるようになります。
// import observable from mobx import { observable } from "mobx"; //create a store with count observable class Store { @observable count = 0; } //export Store export default new Store();
計算されたオブザーバブル
MobXの原則を覚えておいてください。*「最小状態(観測可能状態)を見つけ、すべてを導出(派生状態)」*。
すでに定義されている観測量から導出できる値は、計算値です。 MobXは、より多くの状態の作成を阻止することにより、状態の不整合を回避します。 count
変数が何かが遅れる分数を保持していると想像してください。 監視可能なcount
から派生するcomputed
遅延メッセージを追加できます。
import { observable, computed } from "mobx"; class Store { @observable count = 0; @computed get delayMessage = () => { return 'The train is delayed by' + this.count; }; } export default new Store();
ここで、@computed
は、count
からその値を導出するゲッター関数として機能しています。 delayMessage
は、count
の値が変更されると、自動的に変更を発行します。
行動
アクションは、単に状態を変更する関数です。 MobXは一方向のデータフローをサポートします。つまり、アクションが状態を変更すると、その状態を消費しているすべてのビューが自動的に更新されます。 遅延が増加するとcount
変数を更新するaction
を追加しましょう。
Store { import { observable, computed, action } from "mobx"; class Store { @observable count = 0; @computed get delayMessage = () => { return 'The train is delayed by' + this.count; }; @action updateDelay = delay => { this.count = delay; }; } export default new Store();
すべての状態の変更は、アクションによってのみ実行する必要があることに注意してください。
反応
オブザーバーは、オブザーバブルの変更をサブスクライブし、それらを使用するコンポーネントを再レンダリングします。 反応は、これらの状態変化の単なる副作用です。 これは計算された値と非常に似ていますが、違いは値を計算して返す代わりに、リアクションが単に副次的な操作を実行することです。 簡単に言うと、リアクションは次のとおりです。
状態の変化に反応して発生するはずの副作用(コンポーネントの再レンダリング)
MobXは、 autorun 、whenおよびreactionの3つの主要なタイプの反応関数を提供します。
1. 自動実行
autorun
は、状態が変化するたびに実行される関数です。
autorun(() => { console.log('delay is', this.count); } );
この関数は、count
の値が変更されるたびに実行されます。 重要なのは、count
変数の変更を監視する必要があることを明示的に述べていないことです。 自動実行内でcount
を使用したという事実は、それを依存関係の1つとして使用し、依存関係が変更されるたびに関数をトリガーするのに十分です。
2. いつ
when
は、特定の条件が満たされるたびに副作用を引き起こします。 2つのパラメータを取ります。 最初のパラメーターは、trueを返すまで再評価される関数であり、2番目のパラメーターは、最初の関数がtrueを返すと実行される別の関数です。 簡単な例は次のとおりです。
class MyResource { constructor() { when( // once... () => this.count > 60, // ... then () => console.log("Guest is too late, maybe he's not coming"); ); } }
ここで、when
は、遅延が1時間(60分)を超えているかどうかを確認し、彼が来ていない可能性があることを出力します。
3. 反応
reaction
は、autorun
のバリエーションであり、関数で使用されるデータ(依存関係)をより細かく制御できます。 2つの関数の引数とオプションの3番目の引数を受け入れます。
- 最初の引数(データ関数)はデータの変更を監視し、2番目の引数であるエフェクト関数の入力として使用されるデータを返します。
- 2番目の関数は、最初の関数が受け取ったデータを最初の引数として受け入れ、副作用を実行しますが、データ関数が新しい値を返す場合に限ります。 また、実行中に反応を処理するために使用できる2番目の引数を受け取ります。
次の例は、1回だけ呼び出される反応を示しています。
const reactionDemo = reaction( () => this.count, (count, reaction) => { console.log("reaction demo: invoked. delay is " + count); reaction.dispose(); } ); this.count = 1; // prints: // reaction demo: invoked. delay is = 1 this.count = 2; // prints: // (There are no logging, because of reaction disposed. But, count continue reaction) console.log(this.count); // prints: // 2
MobXの動作
3つの簡単なステップでReactNativeアプリを作成することで、MobXの動作を理解します。
- 状態を定義し、それを観察可能にする
- 状態の変化を監視するビューを作成する
- アクションを使用して状態を変更する
私たちが構築しているもの
ここでは、Unsplash
から画像を取得してユーザーに表示するシンプルなアプリを作成しています。 ユーザーは画像をクリックしてお気に入りに追加することもできます。
アプリケーションはUnsplashAPIを使用してランダムな画像をフェッチします。 ここでAPIキーを生成できます。
プロジェクトをまだ作成していない場合は、以下の手順に従ってください。
- ReactNativeアプリケーションを作成する
$ react-native init UnsplashDemo
または、Expoを使用します。
$ expo init UnsplashDemo
- MobXを追加
$ npm install mobx mobx-react
- プロジェクトを実行する
$ react-native run-<your-os>
または、Expoを使用します。
$ expo start
ステップ1。 状態を定義し、それを観察可能にする
いくつかの画像を検索して結果を保存します。 次に、任意の画像をクリックしてお気に入りに追加できるようにします。 コメントは自明です:
// importing observables and decorate import { decorate, observable, action } from "mobx"; class Store { // observable to save search query text = ''; // action to update text updateText = (text) => { this.text = text; } // observable to save image response from api data = null; // action to call API and search images searchImages = () => { fetch(`https://api.unsplash.com/search/photos?client_id=${API_KEY}&page=1&query=${this.text}&orientation=landscape`) .then(response => response.json()) .then(data => this.setData(data)); }; // observables can be modifies by an action only setData = (data) => { this.data = data; }; } // another way to decorate variables with observable decorate(Store, { text: observable, updateText: action, data: observable, searchImage: action, setData: action, }); // export class export default new Store();
ステップ2。 状態の変化を監視するビューの作成
画像のリストをレンダリングするコンポーネントImageList.js
を作成します。 また、スイッチを切り替えるだけで、お気に入りに追加された画像が表示されます。
- ImageListコンポーネントのボイラープレート:
import React from "react"; import { View, TextInput, Button, FlatList } from 'react-native'; // imports inject and observer from 'mobx-react': import { inject, observer } from "mobx-react"; // components receive Store values as props which we will inject while exporting function ImageList(props) { // destructure variables from store to use const { text, updateText, data, searchImages } = props.store; return ( <> <TextInput // TextInput to get search query from user style={styles.input} value={text} onChangeText={updateText} /> <Button // Button to call API title="Search" style={styles.button} onPress={searchImages} /> /> <FlatList data={data.results} // response from API keyExtractor={(item) => item.id} renderItem={({ item }) => ( <ImageView // reusable component to render image source={{ uri: item.urls.small }} // passing the url onPress={() => {}} // action to add item to favorite /> )} /> </> ); } // inject Store as props to ImageList and make it observe changes in Store export default inject("store")(observer(ImageList));
TextInput
から入力を取得し、Button
を押してUnsplash検索APIを呼び出しています。 応答はdata
observableに保存されており、FlatList
コンポーネントでそれを使用して画像のリストをレンダリングしています。 簡単ですよね? それでは、お気に入りに画像を追加することに移りましょう。
Unsplash API応答の詳細については、unsplash.com/developersにアクセスしてください。
ステップ3。 アクションを使用した状態の変更
ご存知のように、アクションは状態の変更に関与します。これまでのところ、updateText
はtext
observableを変更し、setData
はdata
を変更しました]観察可能。 ここで、favorites
に画像を追加します。これは、状態を保存するための1つの監視可能オブジェクトと、この状態を変更するための1つのアクションが必要であることを意味します。 それらを追加しましょう。
import { decorate, observable, action } from "mobx"; class Store { text = ''; updateText = (text) => {...}; data = null; searchImages = () => {...}; setData = (data) => {...}; // array to save favourite images favorites = []; // action to add images to favorites addToFavorite = (image) => { this.favorites.push(image); this.data = null; this.text = ''; }; } decorate(Store, { text: observable, updateText: action, data: observable, searchImage: action, setData: action, //adding decorators favorites: observable, addToFavorite: action, }); export default new Store();
次に、これらの追加されたオブザーバブルとアクションのビューを更新します。 以前に検索した画像をクリアして、追加したお気に入りの画像を表示したいのですが、これは次の方法で簡単に実行できます。
// previous destructuring const { favorite, addToFavorite} = this.props.store return ( <> {/* TextInput and Button added earlier */} {/* If data is available then show search results otherwise show the favorite images */} {data ? <FlatList // To render list of images style={styles.container} data={data.results} keyExtractor={(item) => item.id} renderItem={({ item }) => ( <ImageView source={{ uri: item.urls.small }} onPress={() => addToFavorite(item.urls.small)} // action to add url to favorite /> )} /> : <FlatList style={styles.container} data={favorites} keyExtractor={(item, index) => index.toString()} renderItem={({ item }) => ( <ImageView source={{ uri: item }} // render favorite images /> )} /> } </> );
これまで、observers
、observables
、actions
を使用してきました。 computed
を追加して、お気に入りに追加された画像の数を表示しましょう。 computed
は、オブザーバブルから派生状態を取得するゲッター関数のように機能します。 次のように追加できます。
import { decorate, observable, action, computed } from "mobx"; class Store { // previously added value get getFavoriteCount() { return this.favorites.length; } } decorate(Store, { // previously added values getFavoriteCount: computed, }); export default new Store();
ビューにもすばやく追加しましょう。
const { getFavoriteCount } = this.props.store; return ( // TextInput, Button <Text style={styles.count}> Images added: {getFavoriteCount} </Text> // FlatList );
ここで、最後に行う必要があるのは、Provider
のstore
をルートコンポーネントに提供することです。 ルートファイルは次のようになります。
import React from 'react'; import ImageList from './src/container/ImageList'; // imports Provider and store import { Provider } from 'mobx-react'; import store from './src/store'; const App = () => { return ( <Provider store={store}> <ImageList /> </Provider> ); }; export default App;
それでおしまい。 私たちのアプリのGIFが実際に動作しているのを見てみましょう:
MobXのobservables
、actions
、observers
、およびcomputed
プロパティについて学習し、単純なReactNativeアプリを構築することでそれらを正常に使用しました。 MobXの学習を楽しんでいただければ幸いです。このチュートリアルは、React Native+MobXの使用を開始するのに役立ちました。 ハッピーコーディング! 👨💻