feat: use function hooks instead of class hooks
This commit is contained in:
@@ -110,6 +110,7 @@ class QueryClient {
|
|||||||
)
|
)
|
||||||
.cast<DataType, ErrorType, PageType>();
|
.cast<DataType, ErrorType, PageType>();
|
||||||
query.updateQueryFn(queryFn);
|
query.updateQueryFn(queryFn);
|
||||||
|
query.updateNextPageFn(nextPage);
|
||||||
cache.addInfiniteQuery(query);
|
cache.addInfiniteQuery(query);
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -314,6 +314,7 @@ class InfiniteQuery<DataType, ErrorType, PageType>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateNextPageFn(InfiniteQueryNextPage<DataType, PageType> nextPage) {
|
void updateNextPageFn(InfiniteQueryNextPage<DataType, PageType> nextPage) {
|
||||||
|
if (state._nextPage == nextPage) return;
|
||||||
state = state.copyWith(nextPage: nextPage);
|
state = state.copyWith(nextPage: nextPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,8 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
import connectivity_plus_macos
|
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
|
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,6 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <connectivity_plus_windows/connectivity_plus_windows_plugin.h>
|
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
|
||||||
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
connectivity_plus_windows
|
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:fl_query/fl_query.dart';
|
import 'package:fl_query/fl_query.dart';
|
||||||
|
import 'package:fl_query_hooks/src/use_query_client.dart';
|
||||||
|
import 'package:fl_query_hooks/src/utils/use_updater.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/src/foundation/diagnostics.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
|
||||||
InfiniteQuery<DataType, ErrorType, PageType>
|
InfiniteQuery<DataType, ErrorType, PageType>
|
||||||
@@ -19,202 +20,60 @@ InfiniteQuery<DataType, ErrorType, PageType>
|
|||||||
bool enabled = true,
|
bool enabled = true,
|
||||||
List<Object?>? keys,
|
List<Object?>? keys,
|
||||||
}) {
|
}) {
|
||||||
return use(UseInfiniteQuery(
|
final rebuild = useUpdater();
|
||||||
queryKey,
|
final client = useQueryClient();
|
||||||
queryFn,
|
final query = useMemoized(() {
|
||||||
nextPage: nextPage,
|
return client.createInfiniteQuery<DataType, ErrorType, PageType>(
|
||||||
initialPage: initialPage,
|
queryKey,
|
||||||
retryConfig: retryConfig,
|
queryFn,
|
||||||
refreshConfig: refreshConfig,
|
initialParam: initialPage,
|
||||||
jsonConfig: jsonConfig,
|
nextPage: nextPage,
|
||||||
onData: onData,
|
jsonConfig: jsonConfig,
|
||||||
onError: onError,
|
refreshConfig: refreshConfig,
|
||||||
enabled: enabled,
|
retryConfig: retryConfig,
|
||||||
keys: keys,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
class UseInfiniteQuery<DataType, ErrorType, PageType>
|
|
||||||
extends Hook<InfiniteQuery<DataType, ErrorType, PageType>> {
|
|
||||||
final InfiniteQueryFn<DataType, PageType> queryFn;
|
|
||||||
final String queryKey;
|
|
||||||
|
|
||||||
final PageType initialPage;
|
|
||||||
final InfiniteQueryNextPage<DataType, PageType> nextPage;
|
|
||||||
|
|
||||||
final RetryConfig retryConfig;
|
|
||||||
final RefreshConfig refreshConfig;
|
|
||||||
final JsonConfig<DataType>? jsonConfig;
|
|
||||||
|
|
||||||
final ValueChanged<PageEvent<DataType, PageType>>? onData;
|
|
||||||
final ValueChanged<PageEvent<ErrorType, PageType>>? onError;
|
|
||||||
|
|
||||||
// widget specific
|
|
||||||
final bool enabled;
|
|
||||||
|
|
||||||
const UseInfiniteQuery(
|
|
||||||
this.queryKey,
|
|
||||||
this.queryFn, {
|
|
||||||
required this.nextPage,
|
|
||||||
required this.initialPage,
|
|
||||||
this.retryConfig = DefaultConstants.retryConfig,
|
|
||||||
this.refreshConfig = DefaultConstants.refreshConfig,
|
|
||||||
this.jsonConfig,
|
|
||||||
this.onData,
|
|
||||||
this.onError,
|
|
||||||
this.enabled = true,
|
|
||||||
super.keys,
|
|
||||||
}) : assert(
|
|
||||||
(jsonConfig != null && enabled) || jsonConfig == null,
|
|
||||||
'jsonConfig is only supported when enabled is true',
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
createState() => _UseInfiniteQueryState<DataType, ErrorType, PageType>();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _UseInfiniteQueryState<DataType, ErrorType, PageType> extends HookState<
|
|
||||||
InfiniteQuery<DataType, ErrorType, PageType>,
|
|
||||||
UseInfiniteQuery<DataType, ErrorType, PageType>> {
|
|
||||||
InfiniteQuery<DataType, ErrorType, PageType>? query;
|
|
||||||
|
|
||||||
VoidCallback? removeListener;
|
|
||||||
|
|
||||||
StreamSubscription<PageEvent<DataType, PageType>>? dataSubscription;
|
|
||||||
StreamSubscription<PageEvent<ErrorType, PageType>>? errorSubscription;
|
|
||||||
|
|
||||||
void rebuild([_]) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> initialize() async {
|
|
||||||
setState(() {
|
|
||||||
_createQuery();
|
|
||||||
|
|
||||||
if (hook.onData != null)
|
|
||||||
dataSubscription = query!.dataStream.listen(hook.onData);
|
|
||||||
if (hook.onError != null)
|
|
||||||
errorSubscription = query!.errorStream.listen(hook.onError);
|
|
||||||
|
|
||||||
removeListener = query!.addListener(rebuild);
|
|
||||||
});
|
|
||||||
if (hook.enabled) {
|
|
||||||
await query!.fetch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _createQuery() {
|
|
||||||
query = QueryClient.of(context).createInfiniteQuery(
|
|
||||||
hook.queryKey,
|
|
||||||
hook.queryFn,
|
|
||||||
initialParam: hook.initialPage,
|
|
||||||
nextPage: hook.nextPage,
|
|
||||||
retryConfig: hook.retryConfig,
|
|
||||||
refreshConfig: hook.refreshConfig,
|
|
||||||
jsonConfig: hook.jsonConfig,
|
|
||||||
);
|
);
|
||||||
}
|
}, [client, queryKey]);
|
||||||
|
|
||||||
@override
|
useEffect(() {
|
||||||
void initHook() {
|
return query.addListener(rebuild);
|
||||||
super.initHook();
|
}, [query]);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
initialize();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
useEffect(
|
||||||
void dispose() {
|
() {
|
||||||
dataSubscription?.cancel();
|
if (enabled) {
|
||||||
errorSubscription?.cancel();
|
query.fetch();
|
||||||
removeListener?.call();
|
}
|
||||||
super.dispose();
|
return null;
|
||||||
}
|
},
|
||||||
|
[enabled],
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
useEffect(() {
|
||||||
void didUpdateHook(oldHook) {
|
query.updateQueryFn(queryFn);
|
||||||
super.didUpdateHook(oldHook);
|
return null;
|
||||||
|
}, [queryFn, query]);
|
||||||
|
|
||||||
if (oldHook.queryKey != hook.queryKey) {
|
useEffect(() {
|
||||||
|
query.updateNextPageFn(nextPage);
|
||||||
|
return null;
|
||||||
|
}, [nextPage, query]);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
StreamSubscription<PageEvent<DataType, PageType>>? dataSubscription;
|
||||||
|
StreamSubscription<PageEvent<ErrorType, PageType>>? errorSubscription;
|
||||||
|
|
||||||
|
if (onData != null) {
|
||||||
|
dataSubscription = query.dataStream.listen(onData);
|
||||||
|
}
|
||||||
|
if (onError != null) {
|
||||||
|
errorSubscription = query.errorStream.listen(onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () {
|
||||||
dataSubscription?.cancel();
|
dataSubscription?.cancel();
|
||||||
errorSubscription?.cancel();
|
errorSubscription?.cancel();
|
||||||
removeListener?.call();
|
};
|
||||||
initialize();
|
}, [onData, onError, query]);
|
||||||
return;
|
|
||||||
} else if (oldHook.enabled != hook.enabled && hook.enabled) {
|
|
||||||
query!.fetch();
|
|
||||||
}
|
|
||||||
if (oldHook.queryFn != hook.queryFn) {
|
|
||||||
query!.updateQueryFn(hook.queryFn);
|
|
||||||
}
|
|
||||||
if (oldHook.nextPage != hook.nextPage) {
|
|
||||||
query!.updateNextPageFn(hook.nextPage);
|
|
||||||
}
|
|
||||||
if (oldHook.onData != hook.onData) {
|
|
||||||
dataSubscription?.cancel();
|
|
||||||
if (hook.onData != null)
|
|
||||||
dataSubscription = query!.dataStream.listen(hook.onData);
|
|
||||||
}
|
|
||||||
if (oldHook.onError != hook.onError) {
|
|
||||||
errorSubscription?.cancel();
|
|
||||||
if (hook.onError != null)
|
|
||||||
errorSubscription = query!.errorStream.listen(hook.onError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
return query;
|
||||||
build(BuildContext context) {
|
|
||||||
if (query == null) {
|
|
||||||
_createQuery();
|
|
||||||
}
|
|
||||||
return query!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
|
||||||
super.debugFillProperties(properties);
|
|
||||||
properties.add(DiagnosticsProperty<InfiniteQueryFn<DataType, PageType>>(
|
|
||||||
'queryFn',
|
|
||||||
hook.queryFn,
|
|
||||||
));
|
|
||||||
properties
|
|
||||||
.add(DiagnosticsProperty<InfiniteQueryNextPage<DataType, PageType>>(
|
|
||||||
'nextPage',
|
|
||||||
hook.nextPage,
|
|
||||||
));
|
|
||||||
properties.add(DiagnosticsProperty<PageType>(
|
|
||||||
'initialPage',
|
|
||||||
hook.initialPage,
|
|
||||||
));
|
|
||||||
properties.add(DiagnosticsProperty<RetryConfig>(
|
|
||||||
'retryConfig',
|
|
||||||
hook.retryConfig,
|
|
||||||
));
|
|
||||||
properties.add(DiagnosticsProperty<RefreshConfig>(
|
|
||||||
'refreshConfig',
|
|
||||||
hook.refreshConfig,
|
|
||||||
));
|
|
||||||
properties.add(DiagnosticsProperty<JsonConfig<DataType>>(
|
|
||||||
'jsonConfig',
|
|
||||||
hook.jsonConfig,
|
|
||||||
));
|
|
||||||
properties
|
|
||||||
.add(DiagnosticsProperty<ValueChanged<PageEvent<DataType, PageType>>>(
|
|
||||||
'onData',
|
|
||||||
hook.onData,
|
|
||||||
));
|
|
||||||
properties
|
|
||||||
.add(DiagnosticsProperty<ValueChanged<PageEvent<ErrorType, PageType>>>(
|
|
||||||
'onError',
|
|
||||||
hook.onError,
|
|
||||||
));
|
|
||||||
properties.add(DiagnosticsProperty<bool>(
|
|
||||||
'enabled',
|
|
||||||
hook.enabled,
|
|
||||||
));
|
|
||||||
properties.add(DiagnosticsProperty<String>(
|
|
||||||
'queryKey',
|
|
||||||
hook.queryKey,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:fl_query/fl_query.dart';
|
import 'package:fl_query/fl_query.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:fl_query_hooks/src/use_query_client.dart';
|
||||||
import 'package:flutter/src/foundation/diagnostics.dart';
|
import 'package:fl_query_hooks/src/utils/use_updater.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
|
||||||
Mutation<DataType, ErrorType, VariablesType>
|
Mutation<DataType, ErrorType, VariablesType>
|
||||||
@@ -17,227 +17,64 @@ Mutation<DataType, ErrorType, VariablesType>
|
|||||||
List<String>? refreshInfiniteQueries,
|
List<String>? refreshInfiniteQueries,
|
||||||
List<Object?>? keys,
|
List<Object?>? keys,
|
||||||
}) {
|
}) {
|
||||||
return use(
|
final rebuild = useUpdater();
|
||||||
UseMutation(
|
final client = useQueryClient();
|
||||||
|
final mutation = useMemoized(() {
|
||||||
|
return client.createMutation<DataType, ErrorType, VariablesType>(
|
||||||
mutationKey,
|
mutationKey,
|
||||||
mutationFn,
|
mutationFn,
|
||||||
retryConfig: retryConfig,
|
retryConfig: retryConfig,
|
||||||
onData: onData,
|
|
||||||
onError: onError,
|
|
||||||
onMutate: onMutate,
|
|
||||||
refreshQueries: refreshQueries,
|
|
||||||
refreshInfiniteQueries: refreshInfiniteQueries,
|
|
||||||
keys: keys,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class UseMutation<DataType, ErrorType, VariablesType, RecoveryType>
|
|
||||||
extends Hook<Mutation<DataType, ErrorType, VariablesType>> {
|
|
||||||
final MutationFn<DataType, VariablesType> mutationFn;
|
|
||||||
final String mutationKey;
|
|
||||||
|
|
||||||
final RetryConfig retryConfig;
|
|
||||||
|
|
||||||
final MutationOnDataFn<DataType, RecoveryType>? onData;
|
|
||||||
final MutationOnErrorFn<ErrorType, RecoveryType>? onError;
|
|
||||||
final MutationOnMutationFn<VariablesType, RecoveryType>? onMutate;
|
|
||||||
|
|
||||||
// hook specific
|
|
||||||
final List<String>? refreshQueries;
|
|
||||||
final List<String>? refreshInfiniteQueries;
|
|
||||||
|
|
||||||
const UseMutation(
|
|
||||||
this.mutationKey,
|
|
||||||
this.mutationFn, {
|
|
||||||
this.retryConfig = DefaultConstants.retryConfig,
|
|
||||||
this.onData,
|
|
||||||
this.onError,
|
|
||||||
this.onMutate,
|
|
||||||
this.refreshQueries,
|
|
||||||
this.refreshInfiniteQueries,
|
|
||||||
super.keys,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
createState() =>
|
|
||||||
_UseMutationState<DataType, ErrorType, VariablesType, RecoveryType>();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _UseMutationState<DataType, ErrorType, VariablesType, RecoveryType>
|
|
||||||
extends HookState<Mutation<DataType, ErrorType, VariablesType>,
|
|
||||||
UseMutation<DataType, ErrorType, VariablesType, RecoveryType>> {
|
|
||||||
Mutation<DataType, ErrorType, VariablesType>? mutation;
|
|
||||||
|
|
||||||
VoidCallback? removeListener;
|
|
||||||
|
|
||||||
StreamSubscription<VariablesType>? mutationSubscription;
|
|
||||||
StreamSubscription<DataType>? dataSubscription;
|
|
||||||
StreamSubscription<ErrorType>? errorSubscription;
|
|
||||||
|
|
||||||
RecoveryType? recoveryData;
|
|
||||||
|
|
||||||
void rebuild([_]) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
void subscribeOnMutate() {
|
|
||||||
if (hook.onMutate != null)
|
|
||||||
mutationSubscription = mutation!.mutationStream.listen(
|
|
||||||
(event) async {
|
|
||||||
recoveryData = await hook.onMutate?.call(event);
|
|
||||||
|
|
||||||
if (hook.onData != null) {
|
|
||||||
dataSubscription?.cancel();
|
|
||||||
subscribeOnData();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hook.onError != null) {
|
|
||||||
errorSubscription?.cancel();
|
|
||||||
subscribeOnError();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void subscribeOnData() {
|
|
||||||
if (hook.onData != null ||
|
|
||||||
hook.refreshInfiniteQueries != null ||
|
|
||||||
hook.refreshQueries != null)
|
|
||||||
dataSubscription = mutation!.dataStream.listen(
|
|
||||||
(event) {
|
|
||||||
final data = hook.onData?.call(event, recoveryData);
|
|
||||||
if (hook.refreshQueries != null) {
|
|
||||||
QueryClient.of(context).refreshQueries(hook.refreshQueries!);
|
|
||||||
}
|
|
||||||
if (hook.refreshInfiniteQueries != null) {
|
|
||||||
QueryClient.of(context)
|
|
||||||
.refreshInfiniteQueries(hook.refreshInfiniteQueries!);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void subscribeOnError() {
|
|
||||||
if (hook.onError != null)
|
|
||||||
errorSubscription = mutation!.errorStream.listen(
|
|
||||||
(event) {
|
|
||||||
return hook.onError?.call(event, recoveryData);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> initialize() async {
|
|
||||||
setState(() {
|
|
||||||
_createMutation();
|
|
||||||
subscribeOnMutate();
|
|
||||||
subscribeOnData();
|
|
||||||
subscribeOnError();
|
|
||||||
removeListener = mutation!.addListener(rebuild);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _createMutation() {
|
|
||||||
mutation = QueryClient.of(context).createMutation(
|
|
||||||
hook.mutationKey,
|
|
||||||
hook.mutationFn,
|
|
||||||
retryConfig: hook.retryConfig,
|
|
||||||
);
|
);
|
||||||
}
|
}, [client, mutationKey]);
|
||||||
|
|
||||||
@override
|
final recoveryData = useState<RecoveryType?>(null);
|
||||||
void initHook() {
|
|
||||||
super.initHook();
|
useEffect(() {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
return mutation.addListener(rebuild);
|
||||||
await initialize();
|
}, [mutation]);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
mutation.updateMutationFn(mutationFn);
|
||||||
|
return null;
|
||||||
|
}, [mutationFn, mutation]);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
if (onMutate != null) {
|
||||||
|
return mutation.mutationStream.listen((event) async {
|
||||||
|
recoveryData.value = await onMutate.call(event);
|
||||||
|
}).cancel;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, [onMutate, mutation]);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
StreamSubscription<DataType>? dataSubscription;
|
||||||
|
StreamSubscription<ErrorType>? errorSubscription;
|
||||||
|
|
||||||
|
dataSubscription = mutation.dataStream.listen((event) {
|
||||||
|
final data = onData?.call(event, recoveryData.value);
|
||||||
|
if (refreshQueries != null) {
|
||||||
|
client.refreshQueries(refreshQueries);
|
||||||
|
}
|
||||||
|
if (refreshInfiniteQueries != null) {
|
||||||
|
client.refreshInfiniteQueries(refreshInfiniteQueries);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
if (onError != null) {
|
||||||
void dispose() {
|
errorSubscription = mutation.errorStream.listen(
|
||||||
mutationSubscription?.cancel();
|
(event) {
|
||||||
dataSubscription?.cancel();
|
return onError(event, recoveryData.value);
|
||||||
errorSubscription?.cancel();
|
},
|
||||||
removeListener?.call();
|
);
|
||||||
super.dispose();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
return () {
|
||||||
void didUpdateHook(oldHook) {
|
|
||||||
super.didUpdateHook(oldHook);
|
|
||||||
|
|
||||||
if (oldHook.mutationKey != hook.mutationKey) {
|
|
||||||
mutationSubscription?.cancel();
|
|
||||||
dataSubscription?.cancel();
|
dataSubscription?.cancel();
|
||||||
errorSubscription?.cancel();
|
errorSubscription?.cancel();
|
||||||
removeListener?.call();
|
};
|
||||||
initialize();
|
}, [onData, onError, recoveryData.value, mutation]);
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (oldHook.mutationFn != hook.mutationFn) {
|
|
||||||
mutation!.updateMutationFn(hook.mutationFn);
|
|
||||||
}
|
|
||||||
if (oldHook.onMutate != hook.onMutate) {
|
|
||||||
mutationSubscription?.cancel();
|
|
||||||
subscribeOnMutate();
|
|
||||||
}
|
|
||||||
if (oldHook.onData != hook.onData ||
|
|
||||||
oldHook.refreshQueries != hook.refreshQueries ||
|
|
||||||
oldHook.refreshInfiniteQueries != hook.refreshInfiniteQueries) {
|
|
||||||
dataSubscription?.cancel();
|
|
||||||
subscribeOnData();
|
|
||||||
mutationSubscription?.cancel();
|
|
||||||
subscribeOnMutate();
|
|
||||||
}
|
|
||||||
if (oldHook.onError != hook.onError) {
|
|
||||||
errorSubscription?.cancel();
|
|
||||||
subscribeOnError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
return mutation;
|
||||||
build(BuildContext context) {
|
|
||||||
if (mutation == null) {
|
|
||||||
_createMutation();
|
|
||||||
}
|
|
||||||
return mutation!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
|
||||||
super.debugFillProperties(properties);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<Mutation<DataType, ErrorType, VariablesType>>(
|
|
||||||
'mutation', mutation),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<String>('mutationKey', hook.mutationKey),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<MutationFn<DataType, VariablesType>>(
|
|
||||||
'mutationFn', hook.mutationFn),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<RetryConfig>('retryConfig', hook.retryConfig),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<MutationOnDataFn<DataType, RecoveryType>>(
|
|
||||||
'onData',
|
|
||||||
hook.onData,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<MutationOnErrorFn<ErrorType, RecoveryType>>(
|
|
||||||
'onError',
|
|
||||||
hook.onError,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<MutationOnMutationFn<VariablesType, RecoveryType>>(
|
|
||||||
'onMutation',
|
|
||||||
hook.onMutate,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:fl_query/fl_query.dart';
|
import 'package:fl_query/fl_query.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:fl_query_hooks/src/use_query_client.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:fl_query_hooks/src/utils/use_updater.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
|
||||||
Query<DataType, ErrorType> useQuery<DataType, ErrorType>(
|
Query<DataType, ErrorType> useQuery<DataType, ErrorType>(
|
||||||
@@ -15,185 +16,54 @@ Query<DataType, ErrorType> useQuery<DataType, ErrorType>(
|
|||||||
final ValueChanged<DataType>? onData,
|
final ValueChanged<DataType>? onData,
|
||||||
final ValueChanged<ErrorType>? onError,
|
final ValueChanged<ErrorType>? onError,
|
||||||
|
|
||||||
// widget specific
|
// hook specific
|
||||||
final bool enabled = true,
|
final bool enabled = true,
|
||||||
}) {
|
}) {
|
||||||
return use(
|
final rebuild = useUpdater();
|
||||||
UseQuery<DataType, ErrorType>(
|
final client = useQueryClient();
|
||||||
|
final query = useMemoized(() {
|
||||||
|
return client.createQuery<DataType, ErrorType>(
|
||||||
queryKey,
|
queryKey,
|
||||||
queryFn,
|
queryFn,
|
||||||
initial: initial,
|
initial: initial,
|
||||||
retryConfig: retryConfig,
|
|
||||||
refreshConfig: refreshConfig,
|
|
||||||
jsonConfig: jsonConfig,
|
jsonConfig: jsonConfig,
|
||||||
onData: onData,
|
refreshConfig: refreshConfig,
|
||||||
onError: onError,
|
retryConfig: retryConfig,
|
||||||
enabled: enabled,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class UseQuery<DataType, ErrorType> extends Hook<Query<DataType, ErrorType>> {
|
|
||||||
final QueryFn<DataType> queryFn;
|
|
||||||
final String queryKey;
|
|
||||||
|
|
||||||
final DataType? initial;
|
|
||||||
|
|
||||||
final RetryConfig retryConfig;
|
|
||||||
final RefreshConfig refreshConfig;
|
|
||||||
final JsonConfig<DataType>? jsonConfig;
|
|
||||||
|
|
||||||
final ValueChanged<DataType>? onData;
|
|
||||||
final ValueChanged<ErrorType>? onError;
|
|
||||||
|
|
||||||
// hook specific
|
|
||||||
final bool enabled;
|
|
||||||
|
|
||||||
const UseQuery(
|
|
||||||
this.queryKey,
|
|
||||||
this.queryFn, {
|
|
||||||
this.initial,
|
|
||||||
this.retryConfig = DefaultConstants.retryConfig,
|
|
||||||
this.refreshConfig = DefaultConstants.refreshConfig,
|
|
||||||
this.jsonConfig,
|
|
||||||
this.onData,
|
|
||||||
this.onError,
|
|
||||||
this.enabled = true,
|
|
||||||
super.keys,
|
|
||||||
}) : assert(
|
|
||||||
(jsonConfig != null && enabled) || jsonConfig == null,
|
|
||||||
'jsonConfig is only supported when enabled is true',
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
HookState<Query<DataType, ErrorType>, UseQuery<DataType, ErrorType>>
|
|
||||||
createState() => _UseQueryState<DataType, ErrorType>();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _UseQueryState<DataType, ErrorType> extends HookState<
|
|
||||||
Query<DataType, ErrorType>, UseQuery<DataType, ErrorType>> {
|
|
||||||
Query<DataType, ErrorType>? query;
|
|
||||||
|
|
||||||
VoidCallback? removeListener;
|
|
||||||
|
|
||||||
StreamSubscription<DataType>? dataSubscription;
|
|
||||||
StreamSubscription<ErrorType>? errorSubscription;
|
|
||||||
|
|
||||||
void rebuild([_]) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _createQuery() {
|
|
||||||
query = QueryClient.of(context).createQuery(
|
|
||||||
hook.queryKey,
|
|
||||||
hook.queryFn,
|
|
||||||
initial: hook.initial,
|
|
||||||
retryConfig: hook.retryConfig,
|
|
||||||
refreshConfig: hook.refreshConfig,
|
|
||||||
jsonConfig: hook.jsonConfig,
|
|
||||||
);
|
);
|
||||||
}
|
}, [client, queryKey]);
|
||||||
|
|
||||||
Future<void> initialize() async {
|
useEffect(() {
|
||||||
setState(() {
|
return query.addListener(rebuild);
|
||||||
_createQuery();
|
}, [query]);
|
||||||
if (hook.onData != null)
|
|
||||||
dataSubscription = query!.dataStream.listen(hook.onData);
|
|
||||||
if (hook.onData != null)
|
|
||||||
errorSubscription = query!.errorStream.listen(hook.onError);
|
|
||||||
|
|
||||||
removeListener = query!.addListener(rebuild);
|
useEffect(() {
|
||||||
});
|
query.updateQueryFn(queryFn);
|
||||||
if (hook.enabled) {
|
return null;
|
||||||
await query!.fetch();
|
}, [queryFn, query]);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
if (enabled) {
|
||||||
|
query.fetch();
|
||||||
}
|
}
|
||||||
}
|
return null;
|
||||||
|
}, [enabled]);
|
||||||
|
|
||||||
@override
|
useEffect(() {
|
||||||
void initHook() {
|
StreamSubscription<DataType>? dataSubscription;
|
||||||
super.initHook();
|
StreamSubscription<ErrorType>? errorSubscription;
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
|
||||||
await initialize();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
if (onData != null) {
|
||||||
void dispose() {
|
dataSubscription = query.dataStream.listen(onData);
|
||||||
dataSubscription?.cancel();
|
}
|
||||||
errorSubscription?.cancel();
|
if (onError != null) {
|
||||||
removeListener?.call();
|
errorSubscription = query.errorStream.listen(onError);
|
||||||
super.dispose();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
return () {
|
||||||
void didUpdateHook(
|
|
||||||
UseQuery<DataType, ErrorType> oldHook,
|
|
||||||
) {
|
|
||||||
super.didUpdateHook(oldHook);
|
|
||||||
|
|
||||||
if (oldHook.queryKey != hook.queryKey) {
|
|
||||||
dataSubscription?.cancel();
|
dataSubscription?.cancel();
|
||||||
errorSubscription?.cancel();
|
errorSubscription?.cancel();
|
||||||
removeListener?.call();
|
};
|
||||||
initialize();
|
}, [onData, onError, query]);
|
||||||
return;
|
|
||||||
} else if (oldHook.enabled != hook.enabled && hook.enabled) {
|
|
||||||
query!.fetch();
|
|
||||||
}
|
|
||||||
if (oldHook.queryFn != hook.queryFn) {
|
|
||||||
query!.updateQueryFn(hook.queryFn);
|
|
||||||
}
|
|
||||||
if (oldHook.onData != hook.onData) {
|
|
||||||
dataSubscription?.cancel();
|
|
||||||
if (hook.onData != null)
|
|
||||||
dataSubscription = query!.dataStream.listen(hook.onData);
|
|
||||||
}
|
|
||||||
if (oldHook.onError != hook.onError) {
|
|
||||||
errorSubscription?.cancel();
|
|
||||||
if (hook.onError != null)
|
|
||||||
errorSubscription = query!.errorStream.listen(hook.onError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
return query;
|
||||||
Query<DataType, ErrorType> build(BuildContext context) {
|
|
||||||
if (query == null) {
|
|
||||||
_createQuery();
|
|
||||||
}
|
|
||||||
return query!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
|
||||||
super.debugFillProperties(properties);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<Query<DataType, ErrorType>>('query', query),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<String>('queryKey', hook.queryKey),
|
|
||||||
);
|
|
||||||
properties.add(DiagnosticsProperty<DataType>('initial', hook.initial));
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<RetryConfig>('retryConfig', hook.retryConfig),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<RefreshConfig>(
|
|
||||||
'refreshConfig',
|
|
||||||
hook.refreshConfig,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<JsonConfig<DataType>>(
|
|
||||||
'jsonConfig',
|
|
||||||
hook.jsonConfig,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<ValueChanged<DataType>>('onData', hook.onData),
|
|
||||||
);
|
|
||||||
properties.add(
|
|
||||||
DiagnosticsProperty<ValueChanged<ErrorType>>('onError', hook.onError),
|
|
||||||
);
|
|
||||||
properties.add(DiagnosticsProperty<bool>('enabled', hook.enabled));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user