言語: 英語 | ポルトガル語 | 中国語 | 日本語 | 韓国語
MobX の Dart 言語バージョン。
透明な関数型リアクティブプログラミング(TFRP)を使用して、Dart アプリの状態管理を強化します。
MobX は、アプリケーションのリアクティブデータを UI に簡単に接続できる状態管理ライブラリです。 この接続は完全に自動であり、非常に自然に感じられます。アプリケーション開発者として、UI(および他の場所)で消費する必要があるリアクティブデータに純粋に集中し、両者を同期させることを心配する必要はありません。
これは本当に魔法ではありませんが、消費されているもの(オブザーバブル)とどこで(リアクション)に関するいくつかのスマートな機能があり、自動的に追跡します。オブザーバブルが変更されると、すべてのリアクションが再実行されます。興味深いのは、これらのリアクションは、単純なコンソールログ、ネットワーク呼び出しから UI の再レンダリングまで、何でもかまわないということです。
MobX は JavaScript アプリにとって非常に効果的なライブラリであり、Dart 言語へのこの移植は同じレベルの生産性をもたらすことを目的としています。
私たちのスポンサーに非常に感謝しています。彼らのおかげで、私たちはオープンソースソフトウェア(OSS)プログラムの一部になることができました。 [スポンサーになる]
MobX をより深く理解するには、MobX クイックスタートガイド をご覧ください。この本は JavaScript バージョンの MobX を使用していますが、コアの概念は Dart および Flutter バージョンにも完全に適用できます。
MobX の中心には、オブザーバブル(Observables)、アクション(Actions)、リアクション(Reactions)という 3 つの重要な概念があります。
オブザーバブルは、アプリケーションのリアクティブ状態を表します。これらは、単純なスカラーから複雑なオブジェクトツリーまでさまざまです。アプリケーションの状態をオブザーバブルのツリーとして定義することにより、UI(またはアプリ内の他のオブザーバー)が使用するリアクティブ状態ツリーを公開できます。
単純なリアクティブカウンターは、次のオブザーバブルで表されます。
import 'package:mobx/mobx.dart';
final counter = Observable(0);
クラスなどのより複雑なオブザーバブルも作成できます。
class Counter {
Counter() {
increment = Action(_increment);
}
final _value = Observable(0);
int get value => _value.value;
set value(int newValue) => _value.value = newValue;
Action increment;
void _increment() {
_value.value++;
}
}
一見すると、これはすぐに手に負えなくなるテンプレートコードのように見えます! これが、上記のコードを次のコードに置き換えることができる mobx_codegen を追加した理由です。
import 'package:mobx/mobx.dart';
part 'counter.g.dart';
class Counter = CounterBase with _$Counter;
abstract class CounterBase with Store {
@observable
int value = 0;
@action
void increment() {
value++;
}
}
クラスのオブザーバブルプロパティをマークするために注釈を使用することに注意してください。はい、ここにはヘッダーのテンプレートコードがありますが、これはどのクラスにも固定されています。より複雑なクラスを構築するにつれて、このテンプレートコードは消え、主に中括弧内のコードに集中するようになります。
注意:注釈は mobx_codegen パッケージを介して利用できます。
何が計算できるか、何が計算されるべきか。自動的に。
アプリケーションの状態は、コア状態と派生状態で構成されます。コア状態は、あなたが扱っているドメインに固有の状態です。たとえば、Contact
エンティティがある場合、firstName
と lastName
は Contact
のコア状態を形成します。ただし、fullName
は派生状態であり、firstName
と lastName
を組み合わせることによって取得されます。
このようなコア状態または他の派生状態に依存する派生状態は、計算オブザーバブルと呼ばれます。基になるオブザーバブルが変更されると、自動的に同期されます。
MobX の状態 = コア状態 + 派生状態
import 'package:mobx/mobx.dart';
part 'contact.g.dart';
class Contact = ContactBase with _$Contact;
abstract class ContactBase with Store {
@observable
String firstName;
@observable
String lastName;
@computed
String get fullName => '$firstName, $lastName';
}
上記の例では、firstName
または lastName
が変更されると、fullName
は自動的に同期されます。
アクションは、オブザーバブルをどのように変更するかを示します。オブザーバブルを直接変更するのではなく、アクションは変更に意味を追加します。たとえば、単に value++
を実行するのではなく、increment()
アクションを発行する方が意味があります。さらに、アクションはすべての通知をバッチ処理し、完了後に変更が通知されるようにします。
したがって、オブザーバーはアクションの原子操作が完了したときにのみ通知されます。
アクションはネストすることもでき、最上位のアクションが完了すると通知が送信されます。
final counter = Observable(0);
final increment = Action((){
counter.value++;
});
クラス内でアクションを作成するときは、注釈を利用できます!
import 'package:mobx/mobx.dart';
part 'counter.g.dart';
class Counter = CounterBase with _$Counter;
abstract class CounterBase with Store {
@observable
int value = 0;
@action
void increment() {
value++;
}
}
MobX.dart は非同期アクションを自動的に処理し、runInAction
でコードをラップする必要はありません。
@observable
String stuff = '';
@observable
bool loading = false;
@action
Future<void> loadStuff() async {
loading = true; //This notifies observers
stuff = await fetchStuff();
loading = false; //This also notifies observers
}
リアクションは、オブザーバブル、アクション、リアクションの MobX トライアドを完成させます。これらはリアクティブシステムのオブザーバーであり、追跡しているオブザーバブルが変更されると通知されます。リアクションには、以下にリストされているいくつかのフレーバーがあります。すべて ReactionDisposer
を返します。これは、リアクションを破棄するために呼び出すことができる関数です。
リアクションの際立った特徴の 1 つは、明示的な配線なしで、すべてのオブザーバブルを自動的に追跡することです。リアクション内でオブザーバブルを読み取る行為だけで、それを追跡するのに十分です!
MobX を使用して記述したコードは、文字通り儀式がないように見えます!
ReactionDisposer autorun(Function(Reaction) fn)
リアクションをすぐに実行し、fn
内で使用されるオブザーバブルの変更時にも実行します。
import 'package:mobx/mobx.dart';
final greeting = Observable('Hello World');
final dispose = autorun((_){
print(greeting.value);
});
greeting.value = 'Hello MobX';
// Done with the autorun()
dispose();
// Prints:
// Hello World
// Hello MobX
ReactionDisposer reaction<T>(T Function(Reaction) predicate, void Function(T) effect)
predicate()
関数内で使用されるオブザーバブルを監視し、predicate が異なる値を返すと effect()
を実行します。predicate
内のオブザーバブルのみが追跡されます。
import 'package:mobx/mobx.dart';
final greeting = Observable('Hello World');
final dispose = reaction((_) => greeting.value, (msg) => print(msg));
greeting.value = 'Hello MobX'; // Cause a change
// Done with the reaction()
dispose();
// Prints:
// Hello MobX
ReactionDisposer when(bool Function(Reaction) predicate, void Function() effect)
predicate()
内で使用されるオブザーバブルを監視し、true
を返すと effect()
を実行します。effect()
が実行されると、when
は自動的に破棄されます。したがって、when
をワンタイムリアクションと見なすことができます。when()
を早期に破棄することもできます。
import 'package:mobx/mobx.dart';
final greeting = Observable('Hello World');
final dispose = when((_) => greeting.value == 'Hello MobX', () => print('Someone greeted MobX'));
greeting.value = 'Hello MobX'; // Causes a change, runs effect and disposes
// Prints:
// Someone greeted MobX
Future<void> asyncWhen(bool Function(Reaction) predicate)
when
と似ていますが、Future
を返します。これは、predicate()
が true
を返すと完了します。これは、predicate()
が true
になるのを待つ便利な方法です。
final completed = Observable(false);
void waitForCompletion() async {
await asyncWhen(() => _completed.value == true);
print('Completed');
}
Observer
アプリで最も視覚的なリアクションの 1 つは UI です。Observer ウィジェット(flutter_mobx
パッケージの一部)は、builder
関数で使用されるオブザーバブルの細かいオブザーバーを提供します。これらのオブザーバブルが変更されると、Observer
は再構築されてレンダリングされます。
以下は、カウンターの例の全体です。
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';
part 'counter.g.dart';
class Counter = CounterBase with _$Counter;
abstract class CounterBase with Store {
@observable
int value = 0;
@action
void increment() {
value++;
}
}
class CounterExample extends StatefulWidget {
const CounterExample({Key key}) : super(key: key);
@override
_CounterExampleState createState() => _CounterExampleState();
}
class _CounterExampleState extends State<CounterExample> {
final _counter = Counter();
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Counter'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Observer(
builder: (_) => Text(
'${_counter.value}',
style: const TextStyle(fontSize: 20),
)),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _counter.increment,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
ここまで読んでいただきありがとうございます🎉🎉🎉。成長し続ける MobX.dart
コミュニティに貢献する方法はいくつかあります。
- "good first issue" とマークされた問題を選択します
- 機能、品質向上の提案を行う
- バグを報告する
- バグを修正する
- 議論に参加し、意思決定を支援する
- ドキュメントを作成および改善します。ドキュメントは非常に重要であり、その重要性は言うまでもありません!
- プルリクエストを送信する
- 参加して
これらの素晴らしい人々に感謝します! (絵文字キー):
このプロジェクトは all-contributors 仕様に従っています。あらゆる種類の貢献を歓迎します!