[Flutter/dart]Reduxパターンでアイテム削除に対応する
前提
以下のようなケースを考えます。
アイテムの一覧がある
ある1つのアイテムの詳細を表示するページがある
詳細ページではそのアイテムの削除ができる
削除したら他のページ(一覧ページなど)に戻る
これはアプリではよくあるパターンだと思います。
課題
reduxパターンを用いている、より具体的にはProviderで状態を管理している場合、以下のような構成になっているのではないでしょうか?
アプリ全体がStoreProviderの子になっており、storeの内容に変化があれば全体がリビルドされる
アイテム詳細ページは、StoreConnectorによってそのアイテムをstoreから切り出す
アイテム詳細ページ内で、アイテムを削除したら所定のページに遷移
//詳細ページに移行
await Navigator.of(context).push(
MaterialPageRoute(
builder: (context)=> StoreConnector<AppState, ItemDetailViewModel>(
converter: (store)
=> ItemDetailViewModel.create(store, itemId),
//2 storeからitemIdのアイテムを取得
builder: (context, model) {
return ItemDetailPage(model); //詳細ページ
},
)
)
);
//削除ボタン
Widget _itemDeleteButton(){
return GestureDetector(
child: const Icon(Icons.delete),
onTap: ()async{
await _deleteItem(); //削除
await Navigator.of(context).push(
//3 別ページに移動
);
}
}
この場合、以下のような課題があります。
アイテムが削除されると、StoreProviderによりアプリ全体がリビルドされる
詳細ページ作成処理も再度実行される
つまり、「storeから指定のアイテムを切り出す処理」(2)も再度実行される
すでにそのidは存在しないので、例外になる
もちろん詳細ページから抜け出すのが2の処理より早ければこの問題は起こりません(抜け出しているから詳細ページ作成処理は走らない)。
しかし、StoreProviderによるリビルドは詳細ページでの処理とは非同期に走るので、先に抜け出せることは保証できません。
解決策
2の処理で、storeに指定のアイテムが存在しない場合はnullを返します。
StoreConnectorによる切り出し部分では、convertorの返り値がnullの場合は別途用意した別のページ(「このアイテムは削除されました」など)に遷移するようにします
await Navigator.of(context).push(
MaterialPageRoute(
builder: (context)=> StoreConnector<AppState, ItemDetailViewModel?>(
converter: (store) =>
ItemDetailViewModel.create(store, itemId),
builder: (context, model) {
if(model == null){
return ItemDeletedPage();
//「このアイテムは削除されました」が表示される
}
return ItemDetailPage(model);
},
)
)
);
最後に
根本的な解決にはなっていない気もしますが、プラットフォームに乗っかるうえではある程度設計に制約が出てしまうのは仕方ないかなと思います。
reduxに限らずProviderを用いていると、このように予期しない、制御もできないタイミングでページがリビルドされたりするので注意が必要ですね。
というか大前提として「削除されたアイテムを取り出すことなんてないだろ」と思って例外処理してないのが悪いですねw
最新記事
すべて表示やりたいこと TextFieldで入力フォームを作りたい。 例えば入力内容が金額の場合、3桁区切りで頭に¥を付けた表記にしたい。 ただしユーザにこれらを入力させるのではなく、ユーザはあくまで数字を入力するだけで、アプリ側で自動でフォーマットしたい。 方法...
現象 やってること iosシミュレータで画像をデバイスのローカルに保存 保存したパスをデータベースに保存 アプリ立ち上げ時にデータベースから画像パスを取得し、そのパスの画像を画面上に表示 起きている現象 iosシミュレータを再起動した場合、上記3で「ファイルパスが見つからな...
やりたいこと 初期値さえ決まればあとは不変な変数がある ただし、コンストラクタ起動時にはまだ決定できない このような変数について late finalで変数を定義 (何らかのタイミングで)初期化されたかどうかをチェックし、されていなければ値を入れる(チェックしないとfina...
コメント