How to read StateNotifierProvider.family without passing value?
408
I figured out.
All I needed was StateProvider
.
final selectedOrderProvider = StateProvider<Order?>((ref) => null);
Then in orderReviewProvider I can easily get orderId.
final orderReviewProvider =
StateNotifierProvider.autoDispose<OrderReviewNotifier, OrderReviewState>(
(ref) {
return OrderReviewNotifier(
ref.read,
orderId: ref.watch(selectedOrderProvider).state!.id,
repository: ref.watch(orderReviewRepositoryProvider),
);
},
);
class OrderReviewNotifier extends StateNotifier<OrderReviewState> {
OrderReviewNotifier(
this.read, {
required int orderId,
required this.repository,
}) : super(OrderReviewState.initial(orderId)) {
getOrderItems();
}
final Reader read;
final OrderReviewRepository repository;
Future<void> getOrderItems() async {
state = state.copyWith(
isLoading: true,
error: null,
);
final result = await repository.getOrderItems(state.orderId);
final checkedItemIds = await repository.getCheckedItemIds(state.orderId);
if (!mounted) {
return;
}
result.when(
data: (data) {
final isAllItemsChecked = !checkedItemIds.containsValue(false) &&
checkedItemIds.length >= data.length;
state = state.copyWith(
orderItems: data,
checkedItemIds: checkedItemIds,
isAllItemsChecked: isAllItemsChecked,
);
},
error: (message) {
state = state.copyWith(
error: message,
);
},
);
state = state.copyWith(
isLoading: false,
);
}
}
The documentation describes the work with this well: link.
Author by
Viacheslav
Updated on November 20, 2022Comments
-
Viacheslav over 1 year
I have implemented StateNotifierProvider with ".family" modifier:
class OrderReviewNotifier extends StateNotifier<OrderReviewState> { final OrderReviewRepository repository; OrderReviewNotifier( this.repository, int orderId, ) : super(OrderReviewState.initial(orderId)); Future<void> getOrderItems() async { //..... } } final orderReviewProvider = StateNotifierProvider.autoDispose .family<OrderReviewNotifier, OrderReviewState, int>( (ref, orderId) { return OrderReviewNotifier( ref.watch(orderReviewRepositoryProvider), orderId, ); }, );
Then in Consumer I watch it:
Consumer( builder: (context, watch, child) { final state = watch(orderReviewProvider(order.id)); //..... }, );
But when I want to read it, I need to pass
order.id
too:onTap: () { context .read(orderReviewProvider(order.id).notifier) .getOrderItems(); },
When I want to send events to notifier from another file, I don't have
order.id
. How to get out of this situation? Thanks for any help! -
SalahAdDin almost 3 yearsActually, I'm doing the same, but still i have to pass the state provider with id to all widget children, and it looks unclean.
-
Viacheslav almost 3 years@SalahAdDin, you don't need to pass
StateProvider
to all widgets, but only to children, that requireStateProvider
, usingConsumer
orHookWidget
. -
SalahAdDin almost 3 yearsThat's why I'm doing actually, but it still looks ugly, hahahahha