はじめに
SwiftのTCAの利点
最近Swiftを勉強しているのですがTCAにどハマりしてしまいました。理由はこの記事がほとんど代弁してくれています。
なんといってもユーザーのアクションと処理内容が明確に分離されているのがいいですよね。Flutterで例を示すとリスト&詳細形式のページを普通にriverpodで実装すると以下のようになると思います。
class DetailNotifier extends StateNotifier<Item> {
DetailNotifier(super.state);
void setItem(Item item) {
state = item;
}
}
final detailProvider = StateNotifierProvider<DetailNotifier, Item>(
(ref) => DetailNotifier(Item(id: "A", description: "This is A.")),
);
//Viewの実装
//リストのアイテムのタップイベント
onTap(Item item) => ref.read(detailProvider.notifier).setItem(item)
この程度ならもっといい実装あるだろというツッコミはさておき、似たような例がよくあるのではないでしょうか。これの何が嫌かというとView(Widget
)に詳細用のItem
をセットするというLogic的な要素が含まれることなんです。これをSwiftではTCAを用いることで改善できます。
//アクション
enum ListAction {
case onSelect(Item)
//...
}
//Viewの実装
List(viewStore.items) { item in
Button(action: {
viewStore.send(.onSelect(item))
}) {
Text(item.name)
}
このようにviewStore
に.onSelect(item)
というアクションを送信するだけで後は裏(Reducer
)でうまいこと動いてくれるんですね。概念図にするとだいたいこんな感じ
左から右に動きが統一されているので単方向データフローと言います。
Flutterの単方向データフロー
Flutterでの単方向データフローはflutter_reduxがかなり前から存在しています。わかりやすいなと思った実装例を載せときます。
しかし更新が2年間止まっていたり、Action1つに対して1つクラスが必要だったり、ReducerでActionの型チェックをするなどと個人的にはイマイチでした。ならば自分で作ってみようじゃないか。
結論
オリジナルで作る際に依存関係でハマってボツりました。pub.devを汚して申し訳ない。代わりに
こちらが見つかったので使ってみましたがかなりの再現度で驚きました。使い方の記事をまた書こうと思います。