fix: state update on unmounted hook and infinite query cache refetch not working

This commit is contained in:
Kingkor Roy Tirtho
2023-02-10 18:52:27 +06:00
parent 02d11d2f46
commit 0af8190cf8
6 changed files with 55 additions and 19 deletions
@@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity_plus","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.9/","native_build":true,"dependencies":[]},{"name":"path_provider_ios","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_ios-2.0.11/","native_build":true,"dependencies":[]}],"android":[{"name":"connectivity_plus","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.9/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_android-2.0.22/","native_build":true,"dependencies":[]}],"macos":[{"name":"connectivity_plus_macos","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_macos-1.2.4/","native_build":true,"dependencies":[]},{"name":"path_provider_macos","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-2.0.6/","native_build":true,"dependencies":[]}],"linux":[{"name":"connectivity_plus_linux","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/","native_build":false,"dependencies":[]},{"name":"path_provider_linux","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-2.1.7/","native_build":false,"dependencies":[]}],"windows":[{"name":"connectivity_plus_windows","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_windows-1.2.2/","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-2.1.3/","native_build":false,"dependencies":[]}],"web":[{"name":"connectivity_plus_web","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.5/","dependencies":[]}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":["connectivity_plus_linux","connectivity_plus_macos","connectivity_plus_web","connectivity_plus_windows"]},{"name":"connectivity_plus_linux","dependencies":[]},{"name":"connectivity_plus_macos","dependencies":[]},{"name":"connectivity_plus_web","dependencies":[]},{"name":"connectivity_plus_windows","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-12-16 21:09:35.483382","version":"3.3.8"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity_plus","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.9/","native_build":true,"dependencies":[]},{"name":"path_provider_ios","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_ios-2.0.11/","native_build":true,"dependencies":[]}],"android":[{"name":"connectivity_plus","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.9/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_android-2.0.22/","native_build":true,"dependencies":[]}],"macos":[{"name":"connectivity_plus_macos","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_macos-1.2.4/","native_build":true,"dependencies":[]},{"name":"path_provider_macos","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-2.0.6/","native_build":true,"dependencies":[]}],"linux":[{"name":"connectivity_plus_linux","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/","native_build":false,"dependencies":[]},{"name":"path_provider_linux","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-2.1.7/","native_build":false,"dependencies":[]}],"windows":[{"name":"connectivity_plus_windows","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_windows-1.2.2/","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-2.1.3/","native_build":false,"dependencies":[]}],"web":[{"name":"connectivity_plus_web","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.5/","dependencies":[]}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":["connectivity_plus_linux","connectivity_plus_macos","connectivity_plus_web","connectivity_plus_windows"]},{"name":"connectivity_plus_linux","dependencies":[]},{"name":"connectivity_plus_macos","dependencies":[]},{"name":"connectivity_plus_web","dependencies":[]},{"name":"connectivity_plus_windows","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-12-24 13:10:41.077116","version":"3.3.8"}
@@ -1,12 +1,36 @@
import 'dart:convert'; import 'dart:convert';
import 'package:fl_query/fl_query.dart'; import 'package:fl_query/fl_query.dart';
import 'package:fl_query_example/components/query_disk_cache.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
class Todo {
int? userId;
int? id;
String? title;
bool? completed;
Todo({this.userId, this.id, this.title, this.completed});
Todo.fromJson(Map<String, dynamic> json) {
userId = json['userId'];
id = json['id'];
title = json['title'];
completed = json['completed'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = {};
data['userId'] = userId;
data['id'] = id;
data['title'] = title;
data['completed'] = completed;
return data;
}
}
final infiniteQueryDiskCacheExampleQuery = final infiniteQueryDiskCacheExampleQuery =
InfiniteQueryJob<List<User>, void, int>( InfiniteQueryJob<List<Todo>, void, int>(
queryKey: 'infiniteQueryDiskCacheExampleQuery', queryKey: 'infiniteQueryDiskCacheExampleQuery',
initialParam: 0, initialParam: 0,
getNextPageParam: (lastPage, lastParam) { getNextPageParam: (lastPage, lastParam) {
@@ -18,11 +42,11 @@ final infiniteQueryDiskCacheExampleQuery =
return firstParam - 5; return firstParam - 5;
}, },
serialize: (data) { serialize: (data) {
return jsonEncode(data.map((user) => user.toJson()).toList()); return jsonEncode(data.map((todo) => todo.toJson()).toList());
}, },
deserialize: (raw) { deserialize: (raw) {
return List.from(jsonDecode(raw)) return List.from(jsonDecode(raw))
.map((user) => User.fromJson(user)) .map((todo) => Todo.fromJson(todo))
.toList(); .toList();
}, },
serializePageParam: (param) => param.toString(), serializePageParam: (param) => param.toString(),
@@ -30,10 +54,10 @@ final infiniteQueryDiskCacheExampleQuery =
task: (_, pageParam, __) async { task: (_, pageParam, __) async {
final res = await http.get( final res = await http.get(
Uri.parse( Uri.parse(
"https://jsonplaceholder.typicode.com/users?_start=$pageParam&_end=${pageParam + 5}"), "https://jsonplaceholder.typicode.com/todos?_start=$pageParam&_end=${pageParam + 5}"),
); );
final body = List.from(jsonDecode(res.body)) final body = List.from(jsonDecode(res.body))
.map((user) => User.fromJson(user)) .map((todo) => Todo.fromJson(todo))
.toList() .toList()
..shuffle(); ..shuffle();
if (pageParam == 0) await Future.delayed(const Duration(seconds: 5)); if (pageParam == 0) await Future.delayed(const Duration(seconds: 5));
@@ -62,12 +86,12 @@ class _InfiniteQueryDiskCacheExampleState
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text("Infinite Query Disk Cache Example")), title: const Text("Infinite Query Disk Cache Example")),
body: InfiniteQueryBuilder<List<User>, void, int>( body: InfiniteQueryBuilder<List<Todo>, void, int>(
job: infiniteQueryDiskCacheExampleQuery, job: infiniteQueryDiskCacheExampleQuery,
externalData: null, externalData: null,
builder: (context, query) { builder: (context, query) {
final data = query.pages final data = query.pages
.expand((page) => page?.toList() ?? []) .expand((page) => page?.toList() ?? <Todo>[])
.toList(); .toList();
return Scaffold( return Scaffold(
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
@@ -81,9 +105,12 @@ class _InfiniteQueryDiskCacheExampleState
body: ListView.builder( body: ListView.builder(
itemCount: data.length, itemCount: data.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return ListTile( return CheckboxListTile(
title: Text(data[index].name!), value: data[index].completed == true,
subtitle: Text(data[index].email!), title: Text(data[index].title ?? ""),
dense: true,
secondary: Text(data[index].id.toString()),
onChanged: null,
); );
}, },
), ),
+4 -4
View File
@@ -195,13 +195,13 @@ abstract class BaseQuery<T extends Object, Outside, Error>
notifyListeners(); notifyListeners();
return data; return data;
} }
final x = hasData && !isPreviousData;
var isOnline = await isNetworkOnline;
/// if isLoading/isRefetching is true that means its already fetching/ /// if isLoading/isRefetching is true that means its already fetching/
/// refetching. So [_execute] again can create a race condition /// refetching. So [_execute] again can create a race condition
if (isLoading || if (isLoading || isRefetching || !isOnline || (hasData && !isPreviousData))
isRefetching || return data;
!(await isNetworkOnline) ||
(hasData && !isPreviousData)) return data;
status = QueryStatus.loading; status = QueryStatus.loading;
notifyListeners(); notifyListeners();
return execute().then((_) { return execute().then((_) {
@@ -45,12 +45,14 @@ class _InfiniteQueryBuilderState<T extends Object, Outside,
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
init(); init();
QueryBowl.of(context).onInfiniteQueriesUpdate<T, Outside, PageParam>( QueryBowl.of(context).onInfiniteQueriesUpdate<T, Outside, PageParam>(
(infiniteQuery) { (infiniteQuery) async {
if (infiniteQuery.queryKey != widget.job.queryKey) return; if (infiniteQuery.queryKey != widget.job.queryKey) return;
if (mounted) if (mounted)
setState(() { setState(() {
this.infiniteQuery = infiniteQuery; this.infiniteQuery = infiniteQuery;
}); });
if (infiniteQuery.isCachedData && !infiniteQuery.fetched)
await infiniteQuery.refetchPages();
}, },
); );
}); });
@@ -83,9 +83,13 @@ InfiniteQuery<T, Outside, PageParam>
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
init(); init();
QueryBowl.of(context).onInfiniteQueriesUpdate<T, Outside, PageParam>( QueryBowl.of(context).onInfiniteQueriesUpdate<T, Outside, PageParam>(
(newInfiniteQuery) { (newInfiniteQuery) async {
if (newInfiniteQuery.queryKey != job.queryKey || !mounted()) return; if (newInfiniteQuery.queryKey != job.queryKey || !mounted()) return;
infiniteQuery.value = newInfiniteQuery; infiniteQuery.value = newInfiniteQuery;
if (!infiniteQuery.value.fetched &&
infiniteQuery.value.isCachedData) {
await infiniteQuery.value.refetchPages();
}
update(); update();
}, },
); );
+4 -1
View File
@@ -11,5 +11,8 @@ const uuid = Uuid();
useForceUpdate() { useForceUpdate() {
final state = useState(false); final state = useState(false);
return () => state.value = !state.value; final isMounted = useIsMounted();
return () {
if (isMounted()) state.value = !state.value;
};
} }