class ListWidget extends HookConsumerWidget {
const ListWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, ref) {
final stateT = ref.watch(listProvider);
final ctrl = ref.read(listProvider.notifier);
final scrollController = useScrollController();
useEffect(() {
Future.delayed(const Duration(milliseconds: 300), () async {
ctrl.initFunc();
});
scrollController.addListener(() {
if (scrollController.offset >=
scrollController.position.maxScrollExtent &&
!scrollController.position.outOfRange) {
print(stateT.list.length);
}
});
return () {
scrollController.removeListener(() {});
scrollController.dispose();
};
}, [
scrollController,
]);
return stateT.isLoading
? const SizedBox(
height: 30,
width: 30,
child: CircularProgressIndicator(),
)
: ListView.builder(
controller: scrollController,
itemBuilder: (context, index) => InkWell(
onTap: () => print(stateT.list.length), child: Text('$index')),
itemCount: stateT.list.length,
);
}
}
This is my widget, where I am using a scroll controller to listen, if the user reaches to the end. And in the end, I need the length of list. But problem is, it is only using giving out of it's initial state! But in the any inkWell, it is printing the current state.
Here is related notifier and state model -->
class ListNotifier extends StateNotifier<ListState> {
ListNotifier() : super(ListState.initState());
initFunc() async {
state = state.copyWith(isLoading: true);
List<int> temp = [];
List.generate(100, (index) => temp.add(index));
await Future.delayed(const Duration(seconds: 1));
state = state.copyWith(isLoading: false, list: temp);
}
}
final listProvider = StateNotifierProvider<ListNotifier, ListState>((ref) {
return ListNotifier();
});
The initFunc() method is an asynchronous method that sets the isLoading field of the state to true, generates a list of integers from 0 to 99 using the List.generate() method and adds them to a temporary list called temp. It then simulates a delay of 1 second using the Future.delayed() method before setting the state's isLoading field to false and setting the list field to the generated temp list using the copyWith() method. And this is state model -->
class ListState extends Equatable {
final List<int> list;
final bool isLoading;
const ListState({
required this.list,
required this.isLoading,
});
@override
List<Object> get props => [list, isLoading];
ListState copyWith({
List<int>? list,
bool? isLoading,
}) {
return ListState(
list: list ?? this.list,
isLoading: isLoading ?? this.isLoading,
);
}
factory ListState.initState() => const ListState(list: [], isLoading: false);
}