files moved to src folder
added flutter_hooks support with example
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import 'package:fl_query/query_bowl.dart';
|
||||
import 'package:fl_query/fl_query.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AnotherComponent extends StatelessWidget {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import 'package:example/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fl_query/fl_query_hooks.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
class HookExample extends HookWidget {
|
||||
const HookExample({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final query = useQuery(job: successJob, externalData: null);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Running the 1st example but with hooks instead"),
|
||||
),
|
||||
body: !query.hasData || query.isLoading || query.isRefetching
|
||||
? const CircularProgressIndicator()
|
||||
: TextButton(
|
||||
child: Text(query.data!),
|
||||
onPressed: () async {
|
||||
await query.refetch();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:example/another_component.dart';
|
||||
import 'package:example/hooks_example.dart';
|
||||
import 'package:example/lazy_query.dart';
|
||||
import 'package:example/mutation_example.dart';
|
||||
import 'package:example/query_with_external_data.dart';
|
||||
@@ -167,6 +168,16 @@ class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
|
||||
);
|
||||
},
|
||||
),
|
||||
ElevatedButton(
|
||||
child: const Text("flutter_hooks Example"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const HookExample(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const AnotherComponent(),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -76,6 +76,13 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_hooks:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_hooks
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.18.5"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@@ -207,4 +214,4 @@ packages:
|
||||
version: "2.1.2"
|
||||
sdks:
|
||||
dart: ">=2.17.1 <3.0.0"
|
||||
flutter: ">=1.17.0"
|
||||
flutter: ">=3.0.0"
|
||||
|
||||
@@ -36,6 +36,7 @@ dependencies:
|
||||
fl_query:
|
||||
path: ../fl_query
|
||||
http: ^0.13.4
|
||||
flutter_hooks: ^0.18.5
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
library fl_query;
|
||||
|
||||
export 'query.dart';
|
||||
export 'query_bowl.dart';
|
||||
export 'query_builder.dart';
|
||||
export 'mutation.dart';
|
||||
export 'mutation_builder.dart';
|
||||
export 'models/query_job.dart';
|
||||
export 'models/mutation_job.dart';
|
||||
export 'src/query.dart';
|
||||
export 'src/query_bowl.dart';
|
||||
export 'src/query_builder.dart';
|
||||
export 'src/mutation.dart';
|
||||
export 'src/mutation_builder.dart';
|
||||
export 'src/models/query_job.dart';
|
||||
export 'src/models/mutation_job.dart';
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
library fl_query_hooks;
|
||||
|
||||
export 'src/hooks/use_query.dart';
|
||||
export 'src/hooks/use_mutation.dart';
|
||||
@@ -0,0 +1,116 @@
|
||||
import 'package:fl_query/src/models/mutation_job.dart';
|
||||
import 'package:fl_query/src/mutation.dart';
|
||||
import 'package:fl_query/src/query_bowl.dart';
|
||||
import 'package:fl_query/src/utils.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
Mutation<T, V> useMutation<T extends Object, V>({
|
||||
required MutationJob<T, V> job,
|
||||
|
||||
/// Called when the query returns new data, on query
|
||||
/// refetch or query gets expired
|
||||
MutationListener<T>? onData,
|
||||
|
||||
/// Called when the query returns error
|
||||
MutationListener<dynamic>? onError,
|
||||
|
||||
/// called right before the mutation is about to run
|
||||
///
|
||||
/// perfect scenario for doing optimistic updates
|
||||
MutationListener<V>? onMutate,
|
||||
List<Object?>? keys,
|
||||
}) {
|
||||
return use(_UseMutation<T, V>(
|
||||
job: job,
|
||||
onData: onData,
|
||||
onError: onError,
|
||||
onMutate: onMutate,
|
||||
keys: keys,
|
||||
));
|
||||
}
|
||||
|
||||
class _UseMutation<T extends Object, V> extends Hook<Mutation<T, V>> {
|
||||
final MutationJob<T, V> job;
|
||||
|
||||
/// Called when the query returns new data, on query
|
||||
/// refetch or query gets expired
|
||||
final MutationListener<T>? onData;
|
||||
|
||||
/// Called when the query returns error
|
||||
final MutationListener<dynamic>? onError;
|
||||
|
||||
/// called right before the mutation is about to run
|
||||
///
|
||||
/// perfect scenario for doing optimistic updates
|
||||
final MutationListener<V>? onMutate;
|
||||
const _UseMutation({
|
||||
required this.job,
|
||||
this.onData,
|
||||
this.onError,
|
||||
this.onMutate,
|
||||
super.keys,
|
||||
});
|
||||
|
||||
@override
|
||||
HookState<Mutation<T, V>, Hook<Mutation<T, V>>> createState() =>
|
||||
_UseMutationHookState();
|
||||
}
|
||||
|
||||
class _UseMutationHookState<T extends Object, V>
|
||||
extends HookState<Mutation<T, V>, _UseMutation<T, V>> {
|
||||
late QueryBowl queryBowl;
|
||||
late final ValueKey<String> uKey;
|
||||
late Mutation<T, V> mutation;
|
||||
|
||||
@override
|
||||
void initHook() {
|
||||
super.initHook();
|
||||
uKey = ValueKey<String>(uuid.v4());
|
||||
mutation = Mutation<T, V>.fromOptions(hook.job);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
queryBowl = QueryBowl.of(context);
|
||||
mutation = queryBowl.addMutation<T, V>(
|
||||
mutation,
|
||||
onData: hook.onData,
|
||||
onError: hook.onError,
|
||||
onMutate: hook.onMutate,
|
||||
key: uKey,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateHook(_UseMutation<T, V> oldHook) {
|
||||
if (oldHook.onData != hook.onData && oldHook.onData != null) {
|
||||
mutation.onDataListeners.remove(oldHook.onData);
|
||||
if (hook.onData != null) mutation.onDataListeners.add(hook.onData!);
|
||||
}
|
||||
if (oldHook.onError != hook.onError && oldHook.onError != null) {
|
||||
mutation.onErrorListeners.remove(oldHook.onError);
|
||||
if (hook.onError != null) mutation.onErrorListeners.add(hook.onError!);
|
||||
}
|
||||
if (oldHook.onMutate != hook.onMutate && oldHook.onMutate != null) {
|
||||
mutation.onMutateListeners.remove(oldHook.onMutate);
|
||||
if (hook.onMutate != null) mutation.onMutateListeners.add(hook.onMutate!);
|
||||
}
|
||||
super.didUpdateHook(oldHook);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
mutation.unmount(uKey);
|
||||
if (hook.onData != null) mutation.onDataListeners.remove(hook.onData);
|
||||
if (hook.onError != null) mutation.onErrorListeners.remove(hook.onError);
|
||||
if (hook.onMutate != null) mutation.onMutateListeners.remove(hook.onMutate);
|
||||
}
|
||||
|
||||
@override
|
||||
Mutation<T, V> build(BuildContext context) {
|
||||
queryBowl = QueryBowl.of(context);
|
||||
return queryBowl.getMutation<T, V>(mutation.mutationKey) ?? mutation;
|
||||
}
|
||||
|
||||
@override
|
||||
String get debugLabel => 'useQuery';
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
import 'package:fl_query/src/models/query_job.dart';
|
||||
import 'package:fl_query/src/query.dart';
|
||||
import 'package:fl_query/src/query_bowl.dart';
|
||||
import 'package:fl_query/src/utils.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
Query<T, Outside> useQuery<T extends Object, Outside>({
|
||||
required QueryJob<T, Outside> job,
|
||||
required Outside externalData,
|
||||
|
||||
/// Called when the query returns new data, on query
|
||||
/// refetch or query gets expired
|
||||
QueryListener<T>? onData,
|
||||
|
||||
/// Called when the query returns error
|
||||
QueryListener<dynamic>? onError,
|
||||
List<Object?>? keys,
|
||||
}) {
|
||||
return use(_UseQuery<T, Outside>(
|
||||
externalData: externalData,
|
||||
job: job,
|
||||
onData: onData,
|
||||
onError: onError,
|
||||
keys: keys,
|
||||
));
|
||||
}
|
||||
|
||||
class _UseQuery<T extends Object, Outside> extends Hook<Query<T, Outside>> {
|
||||
final QueryJob<T, Outside> job;
|
||||
final Outside externalData;
|
||||
|
||||
/// Called when the query returns new data, on query
|
||||
/// refetch or query gets expired
|
||||
final QueryListener<T>? onData;
|
||||
|
||||
/// Called when the query returns error
|
||||
final QueryListener<dynamic>? onError;
|
||||
const _UseQuery({
|
||||
required this.job,
|
||||
required this.externalData,
|
||||
this.onData,
|
||||
this.onError,
|
||||
super.keys,
|
||||
});
|
||||
|
||||
@override
|
||||
HookState<Query<T, Outside>, Hook<Query<T, Outside>>> createState() =>
|
||||
_UseQueryHookState();
|
||||
}
|
||||
|
||||
class _UseQueryHookState<T extends Object, Outside>
|
||||
extends HookState<Query<T, Outside>, _UseQuery<T, Outside>> {
|
||||
late QueryBowl queryBowl;
|
||||
late final ValueKey<String> uKey;
|
||||
late Query<T, Outside> query;
|
||||
|
||||
@override
|
||||
void initHook() {
|
||||
super.initHook();
|
||||
uKey = ValueKey<String>(uuid.v4());
|
||||
query = Query<T, Outside>.fromOptions(
|
||||
hook.job,
|
||||
externalData: hook.externalData,
|
||||
);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
query = QueryBowl.of(context).addQuery<T, Outside>(
|
||||
query,
|
||||
key: uKey,
|
||||
onData: hook.onData,
|
||||
onError: hook.onError,
|
||||
);
|
||||
final hasExternalDataChanged = query.externalData != null &&
|
||||
query.prevUsedExternalData != null &&
|
||||
!isShallowEqual(query.externalData!, query.prevUsedExternalData!);
|
||||
(query.fetched && query.refetchOnMount == true) || hasExternalDataChanged
|
||||
? await query.refetch()
|
||||
: await query.fetch();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateHook(_UseQuery<T, Outside> oldHook) {
|
||||
if (oldHook.externalData != null &&
|
||||
hook.externalData != null &&
|
||||
!isShallowEqual(oldHook.externalData!, hook.externalData!)) {
|
||||
QueryBowl.of(context).fetchQuery(
|
||||
hook.job,
|
||||
externalData: hook.externalData,
|
||||
onData: hook.onData,
|
||||
onError: hook.onError,
|
||||
key: uKey,
|
||||
);
|
||||
} else {
|
||||
if (oldHook.onData != hook.onData && oldHook.onData != null) {
|
||||
query.onDataListeners.remove(oldHook.onData);
|
||||
if (hook.onData != null) query.onDataListeners.add(hook.onData!);
|
||||
}
|
||||
if (oldHook.onError != hook.onError && oldHook.onError != null) {
|
||||
query.onErrorListeners.remove(oldHook.onError);
|
||||
if (hook.onError != null) query.onErrorListeners.add(hook.onError!);
|
||||
}
|
||||
}
|
||||
super.didUpdateHook(oldHook);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
query.unmount(uKey);
|
||||
if (hook.onData != null) query.onDataListeners.remove(hook.onData);
|
||||
if (hook.onError != null) query.onErrorListeners.remove(hook.onError);
|
||||
}
|
||||
|
||||
@override
|
||||
Query<T, Outside> build(BuildContext context) {
|
||||
queryBowl = QueryBowl.of(context);
|
||||
return queryBowl.getQuery<T, Outside>(query.queryKey) ?? query;
|
||||
}
|
||||
|
||||
@override
|
||||
String get debugLabel => 'useQuery';
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import 'package:fl_query/mutation.dart';
|
||||
import 'package:fl_query/fl_query.dart';
|
||||
|
||||
class MutationJob<T extends Object, V> {
|
||||
String _mutationKey;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import 'package:fl_query/query.dart';
|
||||
import 'package:fl_query/src/query.dart';
|
||||
|
||||
class QueryJob<T extends Object, Outside> {
|
||||
// all params
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fl_query/base_operation.dart';
|
||||
import 'package:fl_query/models/mutation_job.dart';
|
||||
import 'package:fl_query/src/base_operation.dart';
|
||||
import 'package:fl_query/src/models/mutation_job.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
enum MutationStatus {
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import 'package:fl_query/models/mutation_job.dart';
|
||||
import 'package:fl_query/mutation.dart';
|
||||
import 'package:fl_query/query_bowl.dart';
|
||||
import 'package:fl_query/utils.dart';
|
||||
import 'package:fl_query/src/models/mutation_job.dart';
|
||||
import 'package:fl_query/src/mutation.dart';
|
||||
import 'package:fl_query/src/query_bowl.dart';
|
||||
import 'package:fl_query/src/utils.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class MutationBuilder<T extends Object, V> extends StatefulWidget {
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fl_query/base_operation.dart';
|
||||
import 'package:fl_query/models/query_job.dart';
|
||||
import 'package:fl_query/src/base_operation.dart';
|
||||
import 'package:fl_query/src/models/query_job.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
enum QueryStatus {
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fl_query/models/query_job.dart';
|
||||
import 'package:fl_query/mutation.dart';
|
||||
import 'package:fl_query/query.dart';
|
||||
import 'package:fl_query/src/models/query_job.dart';
|
||||
import 'package:fl_query/src/mutation.dart';
|
||||
import 'package:fl_query/src/query.dart';
|
||||
import 'package:fl_query/src/utils.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fl_query/utils.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class QueryBowlScope extends StatefulWidget {
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import 'package:fl_query/models/query_job.dart';
|
||||
import 'package:fl_query/query.dart';
|
||||
import 'package:fl_query/query_bowl.dart';
|
||||
import 'package:fl_query/utils.dart';
|
||||
import 'package:fl_query/src/models/query_job.dart';
|
||||
import 'package:fl_query/src/query.dart';
|
||||
import 'package:fl_query/src/query_bowl.dart';
|
||||
import 'package:fl_query/src/utils.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class QueryBuilder<T extends Object, Outside> extends StatefulWidget {
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:fl_query/query.dart';
|
||||
import 'package:fl_query/src/query.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
Future<void> callQueryListeners<T>(Set<QueryListener<T>> listeners, T data) {
|
||||
@@ -19,6 +19,7 @@ dev_dependencies:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
mocktail: ^0.3.0
|
||||
flutter_hooks: ^0.18.5
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:fl_query/models/query_job.dart';
|
||||
import 'package:fl_query/query.dart';
|
||||
import 'package:fl_query/src/models/query_job.dart';
|
||||
import 'package:fl_query/src/query.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user