I'm studying flutter_hooks library. My aim is to fetch data into model and be able to refresh it any time. Also I'd like to refresh data from different screens. Currently I do it this way:
Page class:
class NewPage extends HookWidget{
@override
Widget build(BuildContext context) {
final holder=useState<ModelHolder>(ModelHolder()).value;
final notifier=useListenable(holder.notifier);
final model=notifier.value;
final refresh=useState<bool>(false);
useEffect(() {
print('refetching');
holder.fetch();
},[refresh.value]);
print('model:$model, ${model.hashCode}');
return Scaffold(
appBar: AppBar(
title: Text('Page 2'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
refresh.value=!refresh.value;//trigger refresh
},
child: const Icon(Icons.add),
),
);
}
}
ModelHolder class:
class ModelHolder {
final ValueNotifier<Model?> notifier = ValueNotifier<Model?>(null);
void fetch() async {
await Future.delayed(const Duration(seconds: 2));//do server call
notifier.value=Model('data');
}
}
Model class:
class Model{
final String value;
Model(this.value);
}
Basically this code works as expected. The only thing I'm confused is refresh variable in the NewPage
. Due to this I can't extract hook's logic into custom hook. This is a typical task. I suspect that I'm inventing a wheel. What is the right way of fetching/updating data with flutter_hooks?
UPD: I moved refresh property into ModelHolder
and now able to isolate everything in a custom hook.
holder:
class ModelHolder {
final ValueNotifier<bool> refresher;
final ValueNotifier<Model?> notifier = ValueNotifier<Model?>(null);
ModelHolder(this.refresher);
void fetch() async {
await Future.delayed(const Duration(seconds: 2));//do server call
notifier.value=Model('data');
}
}
Custom hook:
ModelHolder useModel(){
final refresh=useState<bool>(false);
final holder=useState(ModelHolder(refresh)).value;
useListenable(holder.notifier);
useEffect(() {
print('refetching');
holder.fetch();
},[refresh.value]);
return holder;
}
Usage:
Widget build(BuildContext context) {
final holder=useModel();
...
}
And I can pass holder
to other routes to update it from there.