removed dependOnQuery from beacuse of infinite renders

example created for various usecases with various features
hooks now use standard hook API instead of using Hook Class
variable query & mutation not working bug fix
mutation onMutate listeners not getting called bug fix
This commit is contained in:
Kingkor Roy Tirtho
2022-06-24 12:51:27 +06:00
parent 2ead7fd2be
commit d8024714cd
27 changed files with 1117 additions and 680 deletions
@@ -1,17 +0,0 @@
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
class AnotherComponent extends StatelessWidget {
const AnotherComponent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final lol = QueryBowl.of(context).getQuery<String, void>("greetings");
final deadQuery =
QueryBowl.of(context).getQuery<String, String>("external_data");
if (lol?.data == null) return const CircularProgressIndicator();
return Text(
"${lol!.data!} from AnotherComponent\nDeadQuery (It should be null after 10 seconds): ${deadQuery?.data}",
);
}
}
@@ -0,0 +1,115 @@
import 'dart:convert';
import 'dart:math';
import 'package:example/components/basic_query.dart';
import 'package:http/http.dart' as http;
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final basicMutationJob = MutationJob<Map, Map<String, dynamic>>(
mutationKey: "basic-mutation-example",
task: (key, data) async {
final response = await http.post(
Uri.parse(
// to simulate a failing response environment
Random().nextBool()
? "https://jsonplaceholder.typicode.com/posts"
: "https://google.com",
),
headers: {'Content-type': 'application/json; charset=UTF-8'},
body: jsonEncode(data),
);
return jsonDecode(response.body);
},
);
class BasicMutationExample extends StatefulWidget {
const BasicMutationExample({Key? key}) : super(key: key);
@override
State<BasicMutationExample> createState() => _BasicMutationExampleState();
}
class _BasicMutationExampleState extends State<BasicMutationExample> {
late TextEditingController titleController;
late TextEditingController bodyController;
late int id;
@override
void initState() {
super.initState();
id = Random().nextInt(2000000);
titleController = TextEditingController();
bodyController = TextEditingController();
}
@override
void dispose() {
titleController.dispose();
bodyController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Basic Mutation Example",
style: Theme.of(context).textTheme.headline5,
),
MutationBuilder<Map, Map<String, dynamic>>(
job: basicMutationJob,
onMutate: (v) {
QueryBowl.of(context)
.setQueryData<String, void>(successJob.queryKey, (oldData) {
if (oldData?.contains("After Mutate (OPTIMISTIC UPDATE)") ==
true) {
return "$oldData";
}
return "$oldData - After Mutate (OPTIMISTIC UPDATE)";
});
},
builder: (context, mutation) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextField(
controller: titleController,
decoration: const InputDecoration(labelText: "Title"),
),
TextField(
controller: bodyController,
decoration: const InputDecoration(labelText: "Body"),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
final title = titleController.value.text;
final body = bodyController.value.text;
if (body.isEmpty || title.isEmpty) return;
mutation.mutate({
"title": title,
"body": body,
"id": id,
}, onData: (data) {
// resetting the form
titleController.text = "";
bodyController.text = "";
});
},
child: const Text("Post"),
),
const SizedBox(height: 20),
if (mutation.hasData) Text("Response\n${mutation.data}"),
if (mutation.hasError) Text(mutation.error.toString()),
],
),
);
}),
],
);
}
}
@@ -0,0 +1,86 @@
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final successJob = QueryJob<String, void>(
queryKey: "greetings-example",
task: (queryKey, _, __) => Future.delayed(
const Duration(seconds: 2),
() =>
"The work successfully executed. Data: key=($queryKey) value=${Random.secure().nextInt(100)}",
),
);
final canFailJob = QueryJob<String, void>(
queryKey: "failure-example",
task: (queryKey, _, __) => Random().nextBool()
? Future.error("$queryKey operation failed for unknown reason")
: Future.value(
"Successful execution. Result: $queryKey=${Random().nextInt(100)}",
),
);
class BasicQueryExample extends StatelessWidget {
const BasicQueryExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Basic Query Example",
style: Theme.of(context).textTheme.headline5,
),
QueryBuilder<String, void>(
job: successJob,
externalData: null,
builder: (context, query) {
if (!query.hasData || query.isLoading || query.isRefetching) {
return const CircularProgressIndicator();
}
return Row(
children: [
Text(query.data!),
ElevatedButton(
child: const Text("Refetch"),
onPressed: () async {
await query.refetch();
},
),
],
);
},
),
QueryBuilder<String, void>(
job: canFailJob,
externalData: null,
builder: (context, query) {
if (!query.hasData || query.isLoading || query.isRefetching) {
return const CircularProgressIndicator();
}
return Row(
children: [
if (query.hasError)
Text(
"${query.error}. Retrying: ${query.retryAttempts}",
),
if (query.hasData)
Text(
"Success after ${query.retryAttempts}\nData: ${query.data}",
),
ElevatedButton(
child: const Text("Refetch"),
onPressed: () async {
await query.refetch();
},
),
],
);
},
),
],
);
}
}
@@ -0,0 +1,94 @@
import 'dart:convert';
import 'dart:math';
import 'package:example/components/hooks/basic_hook_query.dart';
import 'package:fl_query/fl_query_hooks.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:http/http.dart' as http;
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final basicMutationHookJob = MutationJob<Map, Map<String, dynamic>>(
mutationKey: "basic-hook-mutation-example",
task: (key, data) async {
final response = await http.post(
Uri.parse(
// to simulate a failing response environment
Random().nextBool()
? "https://jsonplaceholder.typicode.com/posts"
: "https://google.com",
),
headers: {'Content-type': 'application/json; charset=UTF-8'},
body: jsonEncode(data),
);
return jsonDecode(response.body);
},
);
class BasicHookMutationExample extends HookWidget {
const BasicHookMutationExample({super.key});
@override
Widget build(BuildContext context) {
final id = useMemoized(() => Random().nextInt(2000000), []);
final titleController = useTextEditingController();
final bodyController = useTextEditingController();
final mutation = useMutation(
job: basicMutationHookJob,
onMutate: (v) {
QueryBowl.of(context)
.setQueryData<String, void>(successHookJob.queryKey, (oldData) {
if (oldData?.contains("After Mutate (OPTIMISTIC UPDATE)") == true) {
return "$oldData";
}
return "$oldData - After Mutate (OPTIMISTIC UPDATE)";
});
},
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Basic Mutation Hook Example",
style: Theme.of(context).textTheme.headline5,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextField(
controller: titleController,
decoration: const InputDecoration(labelText: "Title"),
),
TextField(
controller: bodyController,
decoration: const InputDecoration(labelText: "Body"),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
final title = titleController.value.text;
final body = bodyController.value.text;
if (body.isEmpty || title.isEmpty) return;
mutation.mutate({
"title": title,
"body": body,
"id": id,
}, onData: (data) {
// resetting the form
titleController.text = "";
bodyController.text = "";
});
},
child: const Text("Post"),
),
const SizedBox(height: 20),
if (mutation.hasData) Text("Response\n${mutation.data}"),
if (mutation.hasError) Text(mutation.error.toString()),
],
),
)
],
);
}
}
@@ -0,0 +1,80 @@
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:fl_query/fl_query_hooks.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
final successHookJob = QueryJob<String, void>(
queryKey: "greetings-hook-example",
task: (queryKey, _, __) => Future.delayed(
const Duration(seconds: 2),
() =>
"The work successfully executed. Data: key=($queryKey) value=${Random.secure().nextInt(100)}",
),
);
final canFailHookJob = QueryJob<String, void>(
queryKey: "failure-hook-example",
task: (queryKey, _, __) => Random().nextBool()
? Future.error("$queryKey operation failed for unknown reason")
: Future.value(
"Successful execution. Result: $queryKey=${Random().nextInt(100)}",
),
);
class BasicHookQueryExample extends HookWidget {
const BasicHookQueryExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final successQuery = useQuery(job: successHookJob, externalData: null);
final canFailQuery = useQuery(job: canFailHookJob, externalData: null);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Basic Query Hook Example",
style: Theme.of(context).textTheme.headline5,
),
!successQuery.hasData ||
successQuery.isLoading ||
successQuery.isRefetching
? const CircularProgressIndicator()
: Row(
children: [
Text(successQuery.data!),
ElevatedButton(
child: const Text("Refetch"),
onPressed: () async {
await successQuery.refetch();
},
),
],
),
!canFailQuery.hasData ||
canFailQuery.isLoading ||
canFailQuery.isRefetching
? const CircularProgressIndicator()
: Row(
children: [
if (canFailQuery.hasError)
Text(
"${canFailQuery.error}. Retrying: ${canFailQuery.retryAttempts}",
),
if (canFailQuery.hasData)
Text(
"Success after ${canFailQuery.retryAttempts}\nData: ${canFailQuery.data}",
),
ElevatedButton(
child: const Text("Refetch"),
onPressed: () async {
await canFailQuery.refetch();
},
),
],
)
],
);
}
}
@@ -0,0 +1,43 @@
import 'package:fl_query/fl_query.dart';
import 'package:fl_query/fl_query_hooks.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
final lazyHookQueryJob = QueryJob<String, String>(
queryKey: "lazy-hook-query",
enabled: false,
task: (queryKey, data, _) {
return Future.delayed(const Duration(milliseconds: 500),
() => "Result: key=$queryKey value=$data");
},
);
class LazyHookQueryExample extends HookWidget {
const LazyHookQueryExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final query = useQuery(
job: lazyHookQueryJob,
externalData: "Love",
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Lazy Hook Query Example",
style: Theme.of(context).textTheme.headline5,
),
Row(
children: [
Text("Current Data: ${query.data ?? "Loading"}"),
ElevatedButton(
child: const Text("Refetch Query"),
onPressed: () => query.refetch(),
),
],
),
],
);
}
}
@@ -0,0 +1,49 @@
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:fl_query/fl_query_hooks.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
final mutationHookVariableKeyJob = MutationJob.withVariableKey<String, double>(
task: (queryKey, variables) {
return Future.value("$variables");
},
);
class MutationHookVariableKeyExample extends HookWidget {
const MutationHookVariableKeyExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final id = useState(Random().nextDouble());
final mutation = useMutation(
job: mutationHookVariableKeyJob("mutation-hook-variable-key#${id.value}"),
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Mutation Hook Variable Key Example",
style: Theme.of(context).textTheme.headline5,
),
Row(
children: [
Text("${mutation.mutationKey} Result: ${mutation.data}"),
ElevatedButton(
child: const Text("Generate Random Data"),
onPressed: () {
mutation.mutate(Random().nextDouble());
},
),
ElevatedButton(
child: const Text("New Mutation"),
onPressed: () {
id.value = Random().nextDouble();
},
),
],
),
],
);
}
}
@@ -0,0 +1,58 @@
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:fl_query/fl_query_hooks.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
final queryHookExternalDataJob = QueryJob<String, double>(
queryKey: "query-hook-external-data",
cacheTime: const Duration(seconds: 10),
task: (queryKey, data, _) {
return Future.delayed(const Duration(milliseconds: 500),
() => "Hello from $queryKey with $data");
},
);
class QueryHookExternalDataExample extends HookWidget {
const QueryHookExternalDataExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final externalData = useState(Random().nextDouble() * 200);
final query = useQuery(
job: queryHookExternalDataJob,
externalData: externalData.value,
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Query Hook With External Data Example",
style: Theme.of(context).textTheme.headline5,
),
query.isLoading || query.isRefetching || !query.hasData
? const CircularProgressIndicator()
: Row(
children: [
Container(
width: query.externalData,
height: query.externalData,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
),
child: Center(child: Text(query.externalData.toString())),
),
ElevatedButton(
child: const Text("New Id"),
onPressed: () {
externalData.value = Random().nextDouble() * 200;
},
)
],
)
],
);
}
}
@@ -0,0 +1,49 @@
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:fl_query/fl_query_hooks.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
final queryHookVariableKeyJob = QueryJob.withVariableKey<String, void>(
task: (queryKey, externalData, query) {
return Future.delayed(
const Duration(milliseconds: 500),
() => "QueryKey:${queryKey.split("#").last}",
);
});
class QueryHookVariableKeyExample extends HookWidget {
const QueryHookVariableKeyExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final id = useState(Random().nextDouble() * 200);
final query = useQuery<String, void>(
job: queryHookVariableKeyJob("hook-variable-query#${id.value}"),
externalData: null,
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Query Hook Variable Example",
style: Theme.of(context).textTheme.headline5,
),
query.isLoading || query.isRefetching || !query.hasData
? const CircularProgressIndicator()
: Row(
children: [
Text("Query Result: ${query.data}"),
ElevatedButton(
child: const Text("New Id"),
onPressed: () {
id.value = Random().nextDouble() * 200;
},
),
],
)
],
);
}
}
@@ -0,0 +1,43 @@
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final lazyQueryJob = QueryJob<String, String>(
queryKey: "lazy-query",
enabled: false,
task: (queryKey, data, _) {
return Future.delayed(const Duration(milliseconds: 500),
() => "Result: key=$queryKey value=$data");
},
);
class LazyQueryExample extends StatelessWidget {
const LazyQueryExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Lazy Query Example",
style: Theme.of(context).textTheme.headline5,
),
QueryBuilder<String, String>(
job: lazyQueryJob,
externalData: "Love",
builder: (context, query) {
return Row(
children: [
Text("Current Data: ${query.data ?? "Loading"}"),
ElevatedButton(
child: const Text("Refetch Query"),
onPressed: () => query.refetch(),
),
],
);
},
),
],
);
}
}
@@ -0,0 +1,66 @@
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final mutationVariableKeyJob = MutationJob.withVariableKey<String, double>(
task: (queryKey, variables) {
return Future.value("$variables");
},
);
class MutationVariableKeyExample extends StatefulWidget {
const MutationVariableKeyExample({Key? key}) : super(key: key);
@override
State<MutationVariableKeyExample> createState() =>
_MutationVariableKeyExampleState();
}
class _MutationVariableKeyExampleState
extends State<MutationVariableKeyExample> {
late double id;
@override
void initState() {
super.initState();
id = Random().nextDouble();
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Mutation Variable Key Example",
style: Theme.of(context).textTheme.headline5,
),
MutationBuilder<String, double>(
job: mutationVariableKeyJob("mutation-variable-key#$id"),
builder: (context, mutation) {
return Row(
children: [
Text("${mutation.mutationKey} Result: ${mutation.data}"),
ElevatedButton(
child: const Text("Generate Random Data"),
onPressed: () {
mutation.mutate(Random().nextDouble());
},
),
ElevatedButton(
child: const Text("New Mutation"),
onPressed: () {
setState(() {
id = Random().nextDouble();
});
},
),
],
);
},
)
],
);
}
}
@@ -0,0 +1,74 @@
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final jobWithExternalData = QueryJob<String, double>(
queryKey: "query-external-data",
cacheTime: const Duration(seconds: 10),
task: (queryKey, data, _) {
return Future.delayed(const Duration(milliseconds: 500),
() => "Hello from $queryKey with $data");
},
);
class QueryExternalDataExample extends StatefulWidget {
const QueryExternalDataExample({Key? key}) : super(key: key);
@override
State<QueryExternalDataExample> createState() =>
_QueryExternalDataExampleState();
}
class _QueryExternalDataExampleState extends State<QueryExternalDataExample> {
late double externalData;
@override
void initState() {
super.initState();
externalData = Random().nextDouble() * 200;
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Query With External Data Example",
style: Theme.of(context).textTheme.headline5,
),
QueryBuilder<String, double>(
job: jobWithExternalData,
externalData: externalData,
builder: (context, query) {
if (query.isLoading || query.isRefetching || !query.hasData) {
return const CircularProgressIndicator();
}
return Row(
children: [
Container(
width: query.externalData,
height: query.externalData,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
),
child: Center(child: Text(query.externalData.toString())),
),
ElevatedButton(
child: const Text("New Id"),
onPressed: () {
setState(() {
externalData = Random().nextDouble() * 200;
});
},
)
],
);
},
),
],
);
}
}
@@ -0,0 +1,64 @@
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final queryVariableKeyJob = QueryJob.withVariableKey<String, void>(
task: (queryKey, externalData, query) {
return Future.delayed(
const Duration(milliseconds: 500),
() => "QueryKey:${queryKey.split("#").last}",
);
});
class QueryVariableKeyExample extends StatefulWidget {
const QueryVariableKeyExample({Key? key}) : super(key: key);
@override
State<QueryVariableKeyExample> createState() =>
_QueryVariableKeyExampleState();
}
class _QueryVariableKeyExampleState extends State<QueryVariableKeyExample> {
late double id;
@override
void initState() {
super.initState();
id = Random().nextDouble() * 200;
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"# Query Variable Example",
style: Theme.of(context).textTheme.headline5,
),
QueryBuilder<String, void>(
job: queryVariableKeyJob("variable-query#$id"),
externalData: null,
builder: (context, query) {
if (query.isLoading || query.isRefetching || !query.hasData) {
return const CircularProgressIndicator();
}
return Row(
children: [
Text("Query Result: ${query.data}"),
ElevatedButton(
child: const Text("New Id"),
onPressed: () {
setState(() {
id = Random().nextDouble() * 200;
});
},
),
],
);
},
),
],
);
}
}
@@ -1,36 +0,0 @@
import 'package:example/main.dart';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final dependentQueryJob = QueryJob<String, void>(
queryKey: "dependent-query-job",
task: (queryKey, externalData, query) {
final successQuery =
query.dependOnQuery<String, void>(successJob, externalData: null);
final failedQuery =
query.dependOnQuery<String, void>(failedJob, externalData: null);
if (failedQuery.hasError) return failedQuery.error.toString();
if (successQuery.hasData) return successQuery.data!;
return "No data from success query yet";
});
class DependentQueryExample extends StatelessWidget {
const DependentQueryExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: QueryBuilder<String, void>(
job: dependentQueryJob,
externalData: null,
builder: (context, query) {
if (query.isLoading || query.isRefetching || !query.hasData) {
return const CircularProgressIndicator();
}
return Text(query.data!);
},
),
);
}
}
-27
View File
@@ -1,27 +0,0 @@
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();
},
),
);
}
}
-36
View File
@@ -1,36 +0,0 @@
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final lazyQueryJob = QueryJob<String, String>(
queryKey: "non_enabled_query",
enabled: false,
task: (queryKey, data, _) {
return Future.delayed(const Duration(milliseconds: 500),
() => "Hello from $queryKey with $data");
});
class LazyQuery extends StatelessWidget {
const LazyQuery({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: QueryBuilder<String, String>(
job: lazyQueryJob,
externalData: "Love",
builder: (context, query) {
return Column(
children: [
Text("Query Data::: ${query.data ?? "Loading"}"),
ElevatedButton(
child: const Text("Fetch Query"),
onPressed: () => query.refetch(),
),
],
);
},
),
);
}
}
+46 -150
View File
@@ -1,11 +1,17 @@
import 'dart:math';
import 'package:example/another_component.dart';
import 'package:example/dependent_query_example.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';
import 'package:example/components/basic_mutation.dart';
import 'package:example/components/basic_query.dart';
import 'package:example/components/hooks/basic_hook_mutation.dart';
import 'package:example/components/hooks/basic_hook_query.dart';
import 'package:example/components/hooks/lazy_hook_query.dart';
import 'package:example/components/hooks/mutation_hook_variable_key.dart';
import 'package:example/components/hooks/query_hook_external_data.dart';
import 'package:example/components/hooks/query_hook_variable_key.dart';
import 'package:example/components/lazy_query.dart';
import 'package:example/components/mutation_variable_key.dart';
import 'package:example/components/query_external_data.dart';
import 'package:example/components/query_variable_key.dart';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
import 'dart:async';
@@ -33,21 +39,6 @@ class MyApp extends StatelessWidget {
}
}
final successJob = QueryJob<String, void>(
queryKey: "greetings",
task: (queryKey, _, __) => Future.delayed(const Duration(seconds: 2),
() => "Welcome ($queryKey) ${Random.secure().nextInt(100)}"),
);
final failedJob = QueryJob<String, void>(
queryKey: "failure",
task: (queryKey, _, __) => Random().nextBool()
? Future.error("[$queryKey] Failed for unknown reason")
: Future.value(
"Success, you'll get slowly ${Random().nextInt(100)}!",
),
);
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@@ -56,142 +47,47 @@ class MyHomePage extends StatefulWidget {
}
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
print("LIFE CYCLE STATE: $state");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Fl Query Example"),
),
body: Column(
children: [
Row(
children: [
QueryBuilder<String, void>(
job: successJob,
externalData: null,
builder: (context, query) {
if (!query.hasData || query.isLoading || query.isRefetching) {
return const CircularProgressIndicator();
}
return TextButton(
child: Text(query.data!),
onPressed: () async {
await query.refetch();
},
);
},
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
// Regular Flutter Examples
const BasicQueryExample(),
const QueryExternalDataExample(),
const LazyQueryExample(),
const QueryVariableKeyExample(),
const Divider(),
const BasicMutationExample(),
const MutationVariableKeyExample(),
const Divider(color: Colors.amber, thickness: 5),
Align(
alignment: Alignment.topLeft,
child: Text(
"!Warning! Cool people only...\nFlutter Hooks Example",
style: Theme.of(context).textTheme.headline3,
),
QueryBuilder<String, void>(
job: successJob,
externalData: null,
builder: (context, query) {
if (!query.hasData || query.isLoading || query.isRefetching) {
return const CircularProgressIndicator();
}
return ElevatedButton(
child: Text(query.data!),
onPressed: () async {
await query.refetch();
},
);
},
),
QueryBuilder<String, void>(
job: failedJob,
externalData: null,
builder: (context, query) {
return Row(
children: [
if (query.hasError)
Text(
"${query.error}. Retrying: ${query.retryAttempts}",
),
if (query.hasData)
Text(
"Success after ${query.retryAttempts}. Data: ${query.data}"),
ElevatedButton(
child: Text("Refetch ${query.queryKey}"),
onPressed: () => query.refetch(),
)
],
);
},
),
],
),
ElevatedButton(
child: const Text("External Data Example"),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const QueryWithExternalData(),
),
);
},
),
const SizedBox(height: 10),
ElevatedButton(
child: const Text("Non Enabled Query Example"),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const LazyQuery(),
),
);
},
),
const SizedBox(height: 10),
ElevatedButton(
child: const Text("Mutation Example"),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const MutationExample(),
),
);
},
),
ElevatedButton(
child: const Text("flutter_hooks Example"),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const HookExample(),
),
);
},
),
ElevatedButton(
child: const Text("Dependent Query Example"),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const DependentQueryExample(),
),
);
},
),
const AnotherComponent(),
],
),
),
const Divider(color: Colors.amber, thickness: 5),
// elite flutter_hooks examples for only elite flutter
// developers
const BasicHookQueryExample(),
const QueryHookExternalDataExample(),
const LazyHookQueryExample(),
const QueryHookVariableKeyExample(),
const Divider(),
const BasicHookMutationExample(),
const MutationHookVariableKeyExample(),
],
),
)),
);
}
}
@@ -1,93 +0,0 @@
import 'dart:convert';
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
final postSomethingJob = MutationJob<Map, Map<String, dynamic>>(
mutationKey: "post-something-job",
task: (key, data) async {
final response = await http.post(
Uri.parse(
"https://jsonplaceholder.typicode.com/posts",
),
headers: {'Content-type': 'application/json; charset=UTF-8'},
body: jsonEncode(data),
);
return jsonDecode(response.body);
},
);
class MutationExample extends StatefulWidget {
const MutationExample({Key? key}) : super(key: key);
@override
State<MutationExample> createState() => _MutationExampleState();
}
class _MutationExampleState extends State<MutationExample> {
late TextEditingController titleController;
late TextEditingController bodyController;
late int id;
@override
void initState() {
super.initState();
id = Random().nextInt(2000000);
titleController = TextEditingController();
bodyController = TextEditingController();
}
@override
void dispose() {
titleController.dispose();
bodyController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Post Something")),
body: MutationBuilder<Map, Map<String, dynamic>>(
job: postSomethingJob,
builder: (context, mutation) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextField(
controller: titleController,
decoration: const InputDecoration(labelText: "Title"),
),
TextField(
controller: bodyController,
decoration: const InputDecoration(labelText: "Body"),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
final title = titleController.value.text;
final body = bodyController.value.text;
if (body.isEmpty || title.isEmpty) return;
mutation.mutate({
"title": title,
"body": body,
"id": id,
}, onData: (data) {
// resetting the form
titleController.text = "";
bodyController.text = "";
});
},
child: const Text("Post"),
),
const SizedBox(height: 20),
if (mutation.hasData) Text("Response\n${mutation.data}")
],
),
);
}),
);
}
}
@@ -1,41 +0,0 @@
import 'dart:math';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
final jobWithExternalData = QueryJob<String, String>(
queryKey: "external_data",
cacheTime: const Duration(seconds: 10),
task: (queryKey, data, _) {
return Future.delayed(const Duration(milliseconds: 500),
() => "Hello from $queryKey with $data");
});
class QueryWithExternalData extends StatelessWidget {
const QueryWithExternalData({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: QueryBuilder<String, String>(
job: jobWithExternalData,
externalData: (Random().nextDouble() * 200).toString(),
builder: (context, query) {
if (query.isLoading || query.isRefetching || !query.hasData) {
return const CircularProgressIndicator();
}
return Container(
width: double.parse(query.externalData),
height: double.parse(query.externalData),
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
),
child: Text(query.externalData),
);
},
),
);
}
}