I am developing a new application and testing Riverpod with state notifier and have a question about where I can load my initial data when I'm building a page.
I have following state class:
abstract class SalesOrderListState extends Equatable {
const SalesOrderListState();
@override
List<Object> get props => [];
}
class SalesOrderListInitial extends SalesOrderListState {}
class SalesOrderListLoading extends SalesOrderListState {}
class SalesOrderListSuccess extends SalesOrderListState {
final List<SalesOrderListItem> salesOrderListItems;
SalesOrderListSuccess({
@required this.salesOrderListItems,
});
@override
List<Object> get props => [salesOrderListItems];
}
class SalesOrderListError extends SalesOrderListState {
final String error;
const SalesOrderListError({@required this.error});
@override
List<Object> get props => [error];
}
and this state_notifier class:
final salesOrderListStateNotifierProvider =
StateNotifierProvider<SalesOrderListStateNotifier>(
(ref) => SalesOrderListStateNotifier(ref.read));
class SalesOrderListStateNotifier extends StateNotifier<SalesOrderListState> {
final Reader read;
SalesOrderListStateNotifier(this.read) : super(SalesOrderListInitial());
Future<void> getSalesOrders() async {
final SalesOrderListUseCase _salesOrderListUseCase =
read(salesOrderListUseCaseProvider);
state = SalesOrderListLoading();
final result = await _salesOrderListUseCase.getSalesOrders();
result.fold(
(failure) =>
state = SalesOrderListError(error: mapFailureToMessage(failure)),
(salesOrderListItems) async {
state = SalesOrderListSuccess(salesOrderListItems: salesOrderListItems);
},
);
}
}
Now my widged class (page) use the state notifier like this:
...
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(),
),
body: Consumer(
builder: (context, watch, child) {
final state = watch(salesOrderListStateNotifier.state);
switch (state.runtimeType) {
case SalesOrderListSuccess:
final _salesOrders = (state as SalesOrderListSuccess).salesOrderListItems;
...
print sales orders
...
);
break;
case SalesOrderListError:
return MessageDisplayWidget(
message: (state as SalesOrderListError).error,
);
break;
default:
return LoadingWidget();
}
},
),
);
}
but before the page loads, I have to call
context
.read(salesOrderListStateNotifierProvider)
.getSalesOrders()
What is the best approach to do it?
I have already tried to use a statefull widget and override initstate like this
void initState() {
super.initState();
Future.delayed(Duration.zero).then(
(_) => context
.read(salesOrderListStateNotifierProvider)
.getSalesOrders(),
);
// WidgetsBinding.instance.addPostFrameCallback(
// (_) => context
// .read(salesOrderListStateNotifierProvider)
// .getSalesOrders(),
// );
}
This works but I'm not sure if this is the best approach.
I have a lot of pages where I have to load data before painting it and I'm not sure if converting all this pages to statefull widgets to override initstate is the best solution.