Using same riverpod state provider for multiple pages
2,376
I finally find the answer. thanks @EdwynZN By using family keyword, I can create some thing like a family for each category
class NewsList extends StatefulWidget {
Category category;
NewsList({this.category});
@override
State<StatefulWidget> createState() {
return _NewsListState(category:category);
}
}
class _NewsListState extends State<NewsList> with AutomaticKeepAliveClientMixin<NewsList> {
Category category;
_NewsListState({this.category});
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
// add category.id to newsProvider, instead of getNewsList()
context.read(newsProvider(category.id)).getNewsList();
});
}
@override
Widget build(BuildContext context) {
return Consumer(builder: (ctx, watch, child) {
//newsProvider(category.id) just listen to specific category id and not listen to all ids
return watch(newsProvider(category.id).state).map(
init: (value) {
return Container();
},
loading: (value) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
},
success: (value) {
return Container(child: getNewsItem(value.newsList));
},
serverError: (value) {
return Container();
},
);
});
}
@override
bool get wantKeepAlive => true;
}
//using family here and pass <My State, Category id>
final newsProvider = StateNotifierProvider.family<NewsListNotifier, int>((ref, catID) {
var newsService = ref.watch(newsServiceProvider);
return NewsListNotifier(newsService, catID);
});
class NewsListNotifier extends StateNotifier<NewsListState> {
final NewsService serviceRepository;
int catID;
NewsListNotifier(this.serviceRepository, this.catID) : super(NewsListState.init());
getNewsList() async {
state = NewsListState.loading();
DataResponse request = await serviceRepository.getNewsList(catID, page, 20);
request.maybeWhen(
success: (value) {
if (value.data != null) {
state = NewsListState.success(newsList: value.data);
}
},
error: (error) {
state = NewsListState.serverError(error);
},
orElse: () {},
);
}
}
Comments
-
Erfan Eghterafi over 1 year
I I'm using provider for state management (actually riverpod) In my project I have a tabview and use each tab for a category and each shows news list. tabview size is not fix and I use same page for all tabs and pass category id to page.
The problem is that newsProvider allways keep last category id and all pages show same news list. Who I can separate newsProvider list for each pages?
//create tabview in my stateFullWidget @override Widget build(BuildContext context) { return Scaffold( body: DefaultTabController( length: europeanCountries.length, // europeanCountries has dynamic size child: new Scaffold( appBar: new AppBar( flexibleSpace: new Column( children: [ new TabBar( tabs: europeanCountries.map<Widget>((e) => getTab(e, FontAwesomeIcons.newspaper)).toList()), ], ), ), // dynamically create NewsList and pass category id body: TabBarView(children: europeanCountries.map((catItem) => NewsList(category: Category(title: catItem.title, id:catItem.id))).toList()), ), ) ) } class NewsList extends StatefulWidget { Category category; NewsList({this.category}); @override State<StatefulWidget> createState() { return _NewsListState(category:category); } } class _NewsListState extends State<NewsList> with AutomaticKeepAliveClientMixin<NewsList> { Category category; _NewsListState({this.category}); @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { context.read(newsProvider).getNewsList(category.id); }); } @override Widget build(BuildContext context) { return Consumer(builder: (ctx, watch, child) { return watch(newsProvider.state).map( init: (value) { return Container(); }, loading: (value) { return Container( child: Center( child: CircularProgressIndicator(), ), ); }, success: (value) { return Container(child: getNewsItem(value.newsList)); }, serverError: (value) { return Container(); }, ); }); } @override bool get wantKeepAlive => true; } final newsProvider = StateNotifierProvider.autoDispose<NewsListNotifier>((ref) { var newsService = ref.watch(newsServiceProvider); return NewsListNotifier(newsService); }); class NewsListNotifier extends StateNotifier<NewsListState> { final NewsService serviceRepository; NewsListNotifier(this.serviceRepository) : super(NewsListState.init()); getNewsList(int catID) async { state = NewsListState.loading(); DataResponse request = await serviceRepository.getNewsList(catID); request.maybeWhen( success: (value) { if (value.data != null) { state = NewsListState.success(newsList: value.data); } }, error: (error) { state = NewsListState.serverError(error); }, orElse: () {}, ); } }
-
EdwynZN over 3 yearshave you tried using family to have differents request based on their id? riverpod.dev/docs/concepts/modifiers/family
-
Erfan Eghterafi over 3 yearsYes, It works using family
-