From 0af8190cf80d856303782011521f486b34f20f1c Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Fri, 10 Feb 2023 18:52:27 +0600 Subject: [PATCH] fix: state update on unmounted hook and infinite query cache refetch not working --- .../example/.flutter-plugins-dependencies | 2 +- .../components/infinite_query_disk_cache.dart | 49 ++++++++++++++----- packages/fl_query/lib/src/base_query.dart | 8 +-- .../lib/src/infinite_query_builder.dart | 4 +- .../lib/src/use_infinite_query.dart | 6 ++- packages/fl_query_hooks/lib/src/utils.dart | 5 +- 6 files changed, 55 insertions(+), 19 deletions(-) diff --git a/packages/fl_query/example/.flutter-plugins-dependencies b/packages/fl_query/example/.flutter-plugins-dependencies index 14ff288..a69857c 100644 --- a/packages/fl_query/example/.flutter-plugins-dependencies +++ b/packages/fl_query/example/.flutter-plugins-dependencies @@ -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"} \ No newline at end of file +{"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"} \ No newline at end of file diff --git a/packages/fl_query/example/lib/components/infinite_query_disk_cache.dart b/packages/fl_query/example/lib/components/infinite_query_disk_cache.dart index 416152e..aeb7490 100644 --- a/packages/fl_query/example/lib/components/infinite_query_disk_cache.dart +++ b/packages/fl_query/example/lib/components/infinite_query_disk_cache.dart @@ -1,12 +1,36 @@ import 'dart:convert'; import 'package:fl_query/fl_query.dart'; -import 'package:fl_query_example/components/query_disk_cache.dart'; import 'package:flutter/material.dart'; 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 json) { + userId = json['userId']; + id = json['id']; + title = json['title']; + completed = json['completed']; + } + + Map toJson() { + final Map data = {}; + data['userId'] = userId; + data['id'] = id; + data['title'] = title; + data['completed'] = completed; + return data; + } +} + final infiniteQueryDiskCacheExampleQuery = - InfiniteQueryJob, void, int>( + InfiniteQueryJob, void, int>( queryKey: 'infiniteQueryDiskCacheExampleQuery', initialParam: 0, getNextPageParam: (lastPage, lastParam) { @@ -18,11 +42,11 @@ final infiniteQueryDiskCacheExampleQuery = return firstParam - 5; }, serialize: (data) { - return jsonEncode(data.map((user) => user.toJson()).toList()); + return jsonEncode(data.map((todo) => todo.toJson()).toList()); }, deserialize: (raw) { return List.from(jsonDecode(raw)) - .map((user) => User.fromJson(user)) + .map((todo) => Todo.fromJson(todo)) .toList(); }, serializePageParam: (param) => param.toString(), @@ -30,10 +54,10 @@ final infiniteQueryDiskCacheExampleQuery = task: (_, pageParam, __) async { final res = await http.get( 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)) - .map((user) => User.fromJson(user)) + .map((todo) => Todo.fromJson(todo)) .toList() ..shuffle(); if (pageParam == 0) await Future.delayed(const Duration(seconds: 5)); @@ -62,12 +86,12 @@ class _InfiniteQueryDiskCacheExampleState return Scaffold( appBar: AppBar( title: const Text("Infinite Query Disk Cache Example")), - body: InfiniteQueryBuilder, void, int>( + body: InfiniteQueryBuilder, void, int>( job: infiniteQueryDiskCacheExampleQuery, externalData: null, builder: (context, query) { final data = query.pages - .expand((page) => page?.toList() ?? []) + .expand((page) => page?.toList() ?? []) .toList(); return Scaffold( floatingActionButton: FloatingActionButton( @@ -81,9 +105,12 @@ class _InfiniteQueryDiskCacheExampleState body: ListView.builder( itemCount: data.length, itemBuilder: (context, index) { - return ListTile( - title: Text(data[index].name!), - subtitle: Text(data[index].email!), + return CheckboxListTile( + value: data[index].completed == true, + title: Text(data[index].title ?? ""), + dense: true, + secondary: Text(data[index].id.toString()), + onChanged: null, ); }, ), diff --git a/packages/fl_query/lib/src/base_query.dart b/packages/fl_query/lib/src/base_query.dart index 3d4bff5..7506e7b 100644 --- a/packages/fl_query/lib/src/base_query.dart +++ b/packages/fl_query/lib/src/base_query.dart @@ -195,13 +195,13 @@ abstract class BaseQuery notifyListeners(); return data; } + final x = hasData && !isPreviousData; + var isOnline = await isNetworkOnline; /// if isLoading/isRefetching is true that means its already fetching/ /// refetching. So [_execute] again can create a race condition - if (isLoading || - isRefetching || - !(await isNetworkOnline) || - (hasData && !isPreviousData)) return data; + if (isLoading || isRefetching || !isOnline || (hasData && !isPreviousData)) + return data; status = QueryStatus.loading; notifyListeners(); return execute().then((_) { diff --git a/packages/fl_query/lib/src/infinite_query_builder.dart b/packages/fl_query/lib/src/infinite_query_builder.dart index f78803a..5d4f26f 100644 --- a/packages/fl_query/lib/src/infinite_query_builder.dart +++ b/packages/fl_query/lib/src/infinite_query_builder.dart @@ -45,12 +45,14 @@ class _InfiniteQueryBuilderState( - (infiniteQuery) { + (infiniteQuery) async { if (infiniteQuery.queryKey != widget.job.queryKey) return; if (mounted) setState(() { this.infiniteQuery = infiniteQuery; }); + if (infiniteQuery.isCachedData && !infiniteQuery.fetched) + await infiniteQuery.refetchPages(); }, ); }); diff --git a/packages/fl_query_hooks/lib/src/use_infinite_query.dart b/packages/fl_query_hooks/lib/src/use_infinite_query.dart index ad34286..f411f71 100644 --- a/packages/fl_query_hooks/lib/src/use_infinite_query.dart +++ b/packages/fl_query_hooks/lib/src/use_infinite_query.dart @@ -83,9 +83,13 @@ InfiniteQuery WidgetsBinding.instance.addPostFrameCallback((_) { init(); QueryBowl.of(context).onInfiniteQueriesUpdate( - (newInfiniteQuery) { + (newInfiniteQuery) async { if (newInfiniteQuery.queryKey != job.queryKey || !mounted()) return; infiniteQuery.value = newInfiniteQuery; + if (!infiniteQuery.value.fetched && + infiniteQuery.value.isCachedData) { + await infiniteQuery.value.refetchPages(); + } update(); }, ); diff --git a/packages/fl_query_hooks/lib/src/utils.dart b/packages/fl_query_hooks/lib/src/utils.dart index 549c9aa..7bfb82d 100644 --- a/packages/fl_query_hooks/lib/src/utils.dart +++ b/packages/fl_query_hooks/lib/src/utils.dart @@ -11,5 +11,8 @@ const uuid = Uuid(); useForceUpdate() { final state = useState(false); - return () => state.value = !state.value; + final isMounted = useIsMounted(); + return () { + if (isMounted()) state.value = !state.value; + }; }