fix(fl_query_hooks): fetch query when queryKey changes
This commit is contained in:
@@ -16,7 +16,7 @@ Fl-Query makes asynchronous server state management a breeze in flutter
|
|||||||
- Smart + effective refetching
|
- Smart + effective refetching
|
||||||
- Optimistic updates
|
- Optimistic updates
|
||||||
- Automatically cached data invalidation & unneeded query/mutation garbage collection
|
- Automatically cached data invalidation & unneeded query/mutation garbage collection
|
||||||
- Infinite data pagination via `InfiniteQuery`
|
- Infinite pagination via `InfiniteQuery`
|
||||||
- Easy to write & understand code. Follows DRY (Don't repeat yourself) convention
|
- Easy to write & understand code. Follows DRY (Don't repeat yourself) convention
|
||||||
- Compatible with both vanilla Flutter & elite [flutter_hooks](https://pub.dev/packages/flutter_hooks)
|
- Compatible with both vanilla Flutter & elite [flutter_hooks](https://pub.dev/packages/flutter_hooks)
|
||||||
|
|
||||||
@@ -41,12 +41,22 @@ You can find the documentation (WIP) of fl-query at https://fl-query.vercel.app/
|
|||||||
|
|
||||||
# Basic Usage
|
# Basic Usage
|
||||||
|
|
||||||
First wrap your `MaterialApp` with with `QueryBowlScope` widget
|
Initialize the cache databases in your `main` method
|
||||||
|
|
||||||
|
> fl-query uses [hive](https://pub.dev/packages/hive) for persisting data to disk
|
||||||
|
|
||||||
|
```dart
|
||||||
|
void main()async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await QueryClient.initialize(cachePrefix: 'fl_query_example');
|
||||||
|
runApp(MyApp());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
In `MyApp` Widget's build method wrap your `MaterialApp` with with `QueryClientProvider` widget
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return QueryBowlScope(
|
return QueryClientProvider(
|
||||||
bowl: QueryBowl(),
|
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
title: 'Fl-Query Example App',
|
title: 'Fl-Query Example App',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
@@ -59,85 +69,6 @@ First wrap your `MaterialApp` with with `QueryBowlScope` widget
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Fl-Query has two types of jobs
|
|
||||||
- `QueryJob`: Used for storing GET requests or for storing changeable yet readonly async data
|
|
||||||
- `MutationJob`: Used for POST/PUT/DELETE requests or for mutating/changing data in services or a store asynchronously
|
|
||||||
|
|
||||||
You can write all your query or mutation logic a method parameter named `task` & identify the query uniquely by passing a unique `queryKey`
|
|
||||||
|
|
||||||
Example of a QueryJob:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
final exampleQueryJob = QueryJob<Map, void>(
|
|
||||||
queryKey: "example", // have to be unique
|
|
||||||
task: (queryKey, externalData) async {
|
|
||||||
final res = await http.get("/api/example-data");
|
|
||||||
return jsonDecode(res.body);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
Store the `QueryJob` somewhere globally accessible in your project so you can reuse it later
|
|
||||||
|
|
||||||
Now you can use this `QueryJob` anywhere inside your flutter app inside the build method using a `QueryBuilder` widget
|
|
||||||
|
|
||||||
```dart
|
|
||||||
Widget build(BuildContext context){
|
|
||||||
return QueryBuilder<String, void>(
|
|
||||||
job: exampleQueryJob,
|
|
||||||
externalData: null,
|
|
||||||
builder: (context, query) {
|
|
||||||
if (!query.hasData || query.isLoading) {
|
|
||||||
return const CircularProgressIndicator();
|
|
||||||
}
|
|
||||||
return Row(
|
|
||||||
children: [
|
|
||||||
Text(query.data!),
|
|
||||||
ElevatedButton(
|
|
||||||
child: const Text("Refetch"),
|
|
||||||
onPressed: () async {
|
|
||||||
// refetches the query
|
|
||||||
await query.refetch();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Or if you're an elite **flutter_hooks** user you can use the `useQuery` hook which is exported from the `package:fl_query_hooks/fl_query_hooks.dart` to do the same thing as above
|
|
||||||
|
|
||||||
```dart
|
|
||||||
/* other imports */
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:fl_query_hooks/fl_query_hooks.dart'; // importing the fl-query hook package
|
|
||||||
|
|
||||||
class Example extends HookWidget{
|
|
||||||
Example(super.key);
|
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final query = useQuery(job: exampleQueryJob, externalData: null);
|
|
||||||
|
|
||||||
if (!query.hasData || query.isLoading) {
|
|
||||||
return const CircularProgressIndicator();
|
|
||||||
}
|
|
||||||
return Row(
|
|
||||||
children: [
|
|
||||||
Text(query.data!),
|
|
||||||
ElevatedButton(
|
|
||||||
child: const Text("Refetch"),
|
|
||||||
onPressed: () async {
|
|
||||||
// refetches the query
|
|
||||||
await query.refetch();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
# Why?
|
# Why?
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
|||||||
@@ -36,15 +36,12 @@ InfiniteQuery<DataType, ErrorType, PageType>
|
|||||||
}, [queryKey]);
|
}, [queryKey]);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
return query.addListener(rebuild);
|
final removeListener = query.addListener(rebuild);
|
||||||
}, [query]);
|
|
||||||
|
|
||||||
useEffect(() {
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
query.fetch();
|
query.fetch();
|
||||||
}
|
}
|
||||||
return null;
|
return removeListener;
|
||||||
}, [enabled]);
|
}, [query, enabled]);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
query.updateQueryFn(queryFn);
|
query.updateQueryFn(queryFn);
|
||||||
|
|||||||
@@ -33,21 +33,18 @@ Query<DataType, ErrorType> useQuery<DataType, ErrorType>(
|
|||||||
return query;
|
return query;
|
||||||
}, [queryKey]);
|
}, [queryKey]);
|
||||||
|
|
||||||
useEffect(() {
|
|
||||||
return query.addListener(rebuild);
|
|
||||||
}, [query]);
|
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
query.updateQueryFn(queryFn);
|
query.updateQueryFn(queryFn);
|
||||||
return null;
|
return null;
|
||||||
}, [queryFn, query]);
|
}, [queryFn, query]);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
|
final removeListener = query.addListener(rebuild);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
query.fetch();
|
query.fetch();
|
||||||
}
|
}
|
||||||
return null;
|
return removeListener;
|
||||||
}, [enabled]);
|
}, [query, enabled]);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
StreamSubscription<DataType>? dataSubscription;
|
StreamSubscription<DataType>? dataSubscription;
|
||||||
|
|||||||
Reference in New Issue
Block a user