[英]Riverpod StateNotifierProvider depend on a FutureProvider
我有一個依賴於StateNotifierProvider
的FutureProvider
。 目前它們看起來像下面這樣。
final catalogProvider = StateNotifierProvider<CatalogNotifier, CatalogState>((ref) {
final network = ref.watch(networkProvider.future); // future provider
return CatalogNotifier(network: network);
});
這使我的CatalogNotifier
接受Future<NetworkProvider>
而不是NetworkProvider
並要求我執行如下操作。
await (await.network).doGet(...)
避免等待多個並允許CatalogNotifier
接受裸網絡提供者的最佳方法是什么,這樣我就可以像NetworkProvider
await.network.doGet(...)
這樣寫?
為了完整起見,以下是其他相關供應商
final networkProvider = FutureProvider<Network>((ref) async {
final cache = await ref.watch(cacheProvider.future);
return Network(cacheManager: cache);
});
final cacheProvider = FutureProvider<CacheManager>((ref) async {
final info = await ref.watch(packageInfoProvider.future);
final key = 'cache-${info.buildNumber}';
return CacheManager(Config(
key,
stalePeriod: const Duration(days: 30),
maxNrOfCacheObjects: 100,
));
我確定我可以將我的緩存提供程序作為未來進入 .network 提供程序,因此它不必是FutureProvider
,但我對如何解決上述問題很感興趣,因為在另一種情況下,如果我取決於 3 或 4 個FutureProvider
s,這可能不是一個選項。
使用 riverpod v2 及其代碼生成功能,這變得容易得多,因為您不再需要決定提供程序的類型。 (除非你要)
@riverpod
Future<CatalogController> catalog(CatalogRef ref) async {
final network = await ref.watch(networkProvider.future);
return CatalogController(network: network);
}
您經常希望計算一個值並有一種方法可以從 UI 中顯式重做該計算。 類似於來自.network 的列表,但在 UI 中有一個刷新按鈕。 這可以在 riverpod 2 中建模如下。
@riverpod
Future<CatalogState> myFeed(MyFeedRef ref) async {
final json = await loadData('url');
return CatalogState(json);
}
// and when you want to refresh this from your UI, or from another provider
ref.invalidate(myFeedProvider);
// if you want to also get the new value in that location right after refreshing
final newValue = await ref.refresh(myFeedProvider);
Riverpod 2 還具有提供程序的加載和錯誤屬性。 您可以使用這些來相應地顯示 UI。 雖然如果你想在你的提要加載時或在錯誤 state 中顯示提供者的最后結果,你必須自己使用返回流/BehaviorSubject 的提供者 model,緩存最后一個值等。
這使我的 CatalogNotifier 接受 Future 而不是 >NetworkProvider 並要求我執行以下操作。
我想不出一種方法來獲得你想要的結果。
你不能只接受一個 AsyncValue 並在 statenotifier 中處理它嗎?
final catalogProvider = StateNotifierProvider<CatalogNotifier, CatalogState>((ref) {
final network = ref.watch(networkProvider); // future provider
return CatalogNotifier(network: network);
});
那么你也能:
void someFunction() async {
network.maybeWhen(
data: (network) => AsyncData(await network.doGet(...)),
orElse: () => state = AsyncLoading(),
);
}
你可以讓 AsyncValue 成為 StateNotifier 的子類型,我以 Todo 列表為例。
如下:
class TodoNotifier extends StateNotifier<AsyncValue<List<Todo>>> {
TodoNotifier(this._ref) : super(const AsyncValue.loading()) {
_fetchData();
}
final Ref _ref;
Future<void> _fetchData() async {
state = const AsyncValue.loading();
// todoListProvider is of type FutureProvider
_ref.read(todoListProvider).when(data: (data) {
state = AsyncValue.data(data);
}, error: (err, stackTrace) {
state = AsyncValue.error(err, stackTrace: stackTrace);
}, loading: () {
state = const AsyncValue.loading();
});
}
void addTodo(Todo todo) {
if (state.hasValue) {
final todoList = state.value ?? [];
state = AsyncValue.data(List.from(todoList)..add(todo));
}
}
....
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.