[docs] MutationJob docs added

[docs] fl-query for flutter blog added
This commit is contained in:
Kingkor Roy Tirtho
2022-07-18 18:39:28 +06:00
parent 2a75aefb0f
commit 915f2aecfc
15 changed files with 493 additions and 154 deletions
Generated
-1
View File
@@ -1 +0,0 @@
fl-query
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/melos_fl-query.iml" filepath="$PROJECT_DIR$/melos_fl-query.iml" />
</modules>
</component>
</project>
-11
View File
@@ -1,11 +0,0 @@
<!-- Generated by Melos -->
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Melos -&gt; Bootstrap Workspace" type="ShConfigurationType">
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$USER_HOME$/.pub-cache/bin/melos" />
<option name="SCRIPT_OPTIONS" value="bootstrap" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="false" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<method v="2" />
</configuration>
</component>
-11
View File
@@ -1,11 +0,0 @@
<!-- Generated by Melos -->
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Melos -&gt; Clean Workspace" type="ShConfigurationType">
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$USER_HOME$/.pub-cache/bin/melos" />
<option name="SCRIPT_OPTIONS" value="clean" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="false" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<method v="2" />
</configuration>
</component>
-12
View File
@@ -1,12 +0,0 @@
---
slug: first-blog-post
title: First Blog Post
authors:
name: Gao Wei
title: Docusaurus Core Team
url: https://github.com/wgao19
image_url: https://github.com/wgao19.png
tags: [hola, docusaurus]
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-44
View File
@@ -1,44 +0,0 @@
---
slug: long-blog-post
title: Long Blog Post
authors: endi
tags: [hello, docusaurus]
---
This is the summary of a very long blog post,
Use a `<!--` `truncate` `-->` comment to limit blog post size in the list view.
<!--truncate-->
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-20
View File
@@ -1,20 +0,0 @@
---
slug: mdx-blog-post
title: MDX Blog Post
authors: [slorber]
tags: [docusaurus]
---
Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
:::tip
Use the power of React to create interactive blog posts.
```js
<button onClick={() => alert('button clicked!')}>Click me!</button>
```
<button onClick={() => alert('button clicked!')}>Click me!</button>
:::
Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

-25
View File
@@ -1,25 +0,0 @@
---
slug: welcome
title: Welcome
authors: [slorber, yangshun]
tags: [facebook, hello, docusaurus]
---
[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
Simply add Markdown files (or folders) to the `blog` directory.
Regular blog authors can be added to `authors.yml`.
The blog post date can be extracted from filenames, such as:
- `2019-05-30-welcome.md`
- `2019-05-30-welcome/index.md`
A blog post folder can be convenient to co-locate blog post images:
![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg)
The blog supports tags as well!
**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
@@ -0,0 +1,456 @@
---
slug: fl-query-for-flutter
title: Fl-Query⚡ for Flutter
authors: krtirtho
tags: [flutter, fl-query]
---
### Managing async data & mutations in Flutter is like a breeze now🌬️
![Banner](https://github.com/KRTirtho/fl-query/blob/main/assets/fl-query-banner.png?raw=true)
If youre familiar with [Flutter](http://flutter.dev), youre definitely familiar with `FutureBuilder`. After all this is the only way you can fetch data in Flutter with proper state, or is it? But you mightve noticed every time the Widget gets rebuild the Future is run along too unless you declare your `Future` in `initState`
But even if you declare your future in `initState` to avoid reruns across rebuilds it will still rerun when the Widget gets disposed & mounted again. So whats the solution? Ans: `FutureProvider` from [riverpod](http://riverpod.dev) or [provider](https://pub.dev/packages/provider)
Hold on a sec, but its not another riverpod/provider article? No, it's not.
Yeah, to cache your future results or server response in you can use `FutureProvider`. It can store & distribute the result all across the application without multiple reruns of the same operation. But what happens when the Data becomes expired or stale? What if your app wont need that data after some time but the data still wasting RAM?
This is where **Fl-Query** comes to play. Its an *Async Data + Mutation Manager for Flutter that caches, fetches, automatically refetches stale data.* Similar to [Tanstack Query](http://tanstack.com/query) in the World of web development, but only the concept is implemented & The API is very similar to what Flutter Developers are used to & so it makes everyone feel like home
Enough talk lets jump to the big part.
## What does it offer?
- Async data caching & invalidation
- Smart & highly configurable refetch mechanism that smartly updates stale/expired data in the background when needed
- Declarative way to define asynchronous operations
- Garbage Collects Query & Mutation. That means unused queries sitting in the Cache for long time gets automatically removed
- Code & **data** reusability because of persisted data & Query/Mutation **Job** API
- Optimistic updates
- Lazy Loading Queries. Run you defined asynchronous task or operation when needed
- Zero Configuration out of the box Global Store that no one ever have to touch
- Supports both Vanilla Flutter & [Flutter Hooks](https://pub.dev/packages/flutter_hooks)
## Lets see some Code
```dart
// A QueryJob is where the Logic of how the data should be
// fetched can defined. The task callback is a PURE Function
// & have access to external resources through the second
// parameter where the first parameter is the queryKey
final successJob = QueryJob<String, void>(
queryKey: "query-example",
task: (queryKey, externalData) => Future.delayed(
const Duration(seconds: 2),
() =>
"The work successfully executed. Data: key=($queryKey) value=${
Random.secure().nextInt(100)
}",
),
);
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// QueryBowlScope creates a Bowl (metaphor for Collection/Store)
// for all the Queries & Mutations
return QueryBowlScope(
child: MaterialApp(
title: 'Fl-Query Quick Start',
theme: ThemeData(
useMaterial3: true,
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
),
);
}
}
class BasicExample extends StatelessWidget {
const BasicExample({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 Widget provides the expected query
// instances through the builder callback based on
// the passed job & externalData argument
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();
},
), // Text
],
); // Row
},
), // QueryBuilder
],
);
}
}
```
Heres three key important part in the code
- [`QueryBowlScope`](https://fl-query.vercel.app/docs/basics/QueryBowlScope): It's the store where all queries & mutations are stored and distributed throughout the application
- [`QueryJob`](https://fl-query.vercel.app/docs/basics/QueryJob): This what one can use to declare and define the asynchronous operations that retrieves data from server or any other place
- [`QueryBuilder`](https://fl-query.vercel.app/docs/basics/Queries#querybuilder): It creates appropriate `Query` by using the provided `job` & provides the `Query` in the builder method. It is the way the data & the UI connects
`QueryBowlScope` & `QueryJob` has many properties that can be configured & changed in a way that best suits your application. Most of their properties are some. But properties defined in `QueryBowlScope` are global configuration where `QueryJob` is specific to that very `Query`
## Query External Data
One thing you mightve notice or have been thinking that the task function is separated from the Widget so how would you use other services, classes, methods or data in it. Simply, how will give inputs to a Query Task or the asynchronous operation? This is where the second parameter of `QueryJob`s task callback comes to play. You can use the `QueryBuilder`s `externalData` named argument to pass data to the task callback. You can literally use anything as externalData. Just pass the Type as Type Parameter to `QueryJob` & `QueryBuilder`
QueryJob with externalData example:
```dart
// This job requires a pre-configured HTTP Client from the http package
// as externalData
// The first Type Parameter is the Type of returned Data & 2nd one is the Type
// of externalData
final anotherJob = QueryJob<String, Client>(
queryKey: "another-unique-key",
task: (queryKey, httpClient){
return httpClient
.get("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.body);
}
);
```
Now lets use this job inside a Widget
```dart
Widget build(BuildContext context) {
// getting the instance of Client provided by the [provider] package
final client = Provider.of<Client>(context);
return QueryBuilder<String, void>(
job: anotherJob,
// passing the client as externalData
externalData: client,
builder: (context, query) {
if (!query.hasData || query.isLoading) {
return const CircularProgressIndicator();
}
// remember to always show a fallback widget/screen for errors too.
// It keeps the user aware of status of the application their using
// & saves their time
else if(query.hasError && query.isError){
return Text(
"My disappointment is immeasurable & my day is ruined for this stupid error: $error",
);
}
return Row(
children: [
// accessing the returned data & showing it
Text(query.data["title"]),
ElevatedButton(
child: const Text("Refetch"),
onPressed: () async {
await query.refetch();
},
),
],
);
},
);
}
```
Thats it. It is that easy to provide `externalData` to a Query task
> By default, when `externalData` changes the Query is not refetched. But you can change this behavior if you want the query to refetch everytime `externalData` changes. Just set `refetchOnExternalDataChange` to true in `QueryJob` for that specific Query or in `QueryBowlScope` for all Queries
>
## Query Refetch & Stale Time
Every query is updated when needed. But you can trigger a refetch for a Query or multiple queries manually. This can be useful after a mutation or the application data has changed for sure. The `Query.refetch` allows to refetch a single query where `QueryBowl.of(context).refetchQueries` allows refetching multiple queries at the same time
Heres an example of single query refetch:
```dart
ElevatedButton(
onPressed: () async {
await query.refetch();
}
child: Text("Refetch")
);
```
Now for refetching multiple queries:
```dart
TextField(
controller: controller,
onSubmitted: (value){
QueryBowl.of(context).refetchQueries(
[exampleJob1.queryKey, exampleJob2.queryKey]
);
}
);
```
> The `QueryBowl.of` method gives access to many methods used internally in Fl-Query. Its just an imperative way to do some things when it's necessary. It provides access to many useful methods & properties e.g. `refetchQueries`, `invalidateQueries`, `resetQueries`, `isFetching` etc
>
Stale Time means the amount of time when after a Query or multiple Querys data should be considered as outdated
By default, Queries become stale as soon as fetch/refetch completes. But this can be configured using the `staleTime` property of `QueryBowlScope` for global configuration or per Query basis using the `QueryJob`'s property
```dart
final job = QueryJob<String, Client>(
queryKey: "another-unique-key",
// now the data of the query will become stale after 30 seconds when the
// fetch/refetch executes
staleTime: Duration(seconds: 30),
task: (queryKey, httpClient){
return httpClient
.get("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.body);
}
);
```
## Query status
A Query can be in following statuses
- `isSuccess`: When the task function returned data successfully
- `isError`: When the task function returned an error
- `isLoading`: When the task function is running
- `isRefetching`: When new data is being fetched or simply the `refetch` method is executing
- `isIdle`: When there's no data & `Query`'s task has not been yet run
These are Query Progress Status theres another type of status of Query too. Theyre called Data availability status. Following are:
- `hasData`: When query contains data no matters what's happening Basically, `query.data != null`
- `hasError`: When the query contains error. Basically, `query.error != null`
> Remember, dont use `isLoading` only for Loading Indicators as even if the Query `isSucessful` the `data` can still be null. So use `!query.hasData` || `query.isLoading` to ensure theres no null exceptions
>
That is all about queries. It has so much more useful functionalities & features that it cant be covered in a single article. Please visit the [docs](https://fl-query.vercel.app/) for more info ([https://fl-query.vercel.app](https://fl-query.vercel.app/))
## Mutations
Queries are used for retrieving Data or for GET requests where Mutation are, Unlike queries, typically used to create/update/delete data or perform server side effects
Basically, a mutation is a type of asynchronous operation that modifies already available data or adds data in a store or remote server
Just like QueryJob Mutation has `MutationJob` that can be used to define the mutation operation or configuring different stuff
Heres a MutationJob example:
```dart
final basicMutationJob = MutationJob<Map, Map<String, dynamic>>(
// instead of queryKey mutation has mutationKey
mutationKey: "unique-mutation-key",
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);
},
);
```
The `task` callback of MutationJob has a variable parameter. It might seem like externalData from QueryJob, but it's a little different. Instead of passing data through externalData argument of QueryBuider, youve to pass it through `mutate` or `mutateAsync` method of Mutation
Now lets use this `MutationJob` with our `MutationBuilder`
```dart
Widget build(context){
return MutationBuilder<Map, Map<String, dynamic>>(
job: basicMutationJob,
builder: (context, mutation) {
return Padding(
padding: const EdgeInsets.all(8.0),
// Its just basic Form
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;
// calling the mutate of the mutation
mutation.mutate({
"title": title,
"body": body,
"id": 42069, // the holy number as ID
}, onData: (data) {
// resetting the form
titleController.text = "";
bodyController.text = "";
});
},
child: const Text("Post"),
),
const SizedBox(height: 20),
// accessing the mutation result
if (mutation.hasData) Text("Response\n${mutation.data}"),
if (mutation.hasError) Text(mutation.error.toString()),
],
),
);
});
}
```
Above, there are 2 text fields that provide title and body of a Post & were running the mutation whenever the submit button is pressed. The `mutate` method accepts 3 arguments
- 1st parameter/Variables
- `onData`: A callback that runs when result is available & Mutation is successful
- `onError`: A callback that runs when result is available & Mutation is successful
### Optimistic Updates
The most interesting part of `Mutation`s are the `onMutate` callback of `MutationBuilder`. Its a callback that runs just before executing the `MutationJob.task`. Here you can do all sort of crazy stuff. Such as adding predicted data to different queries before data being returned from the server or deleting an entire Query or anything you want. But in combination with `onData` you can update your applications data Optimistically, so the user doesnt have to wait
> Optimistic update means, updating Query data with predictable data before actually getting back any result. Then, when the real data arrives, replace the predicted data with the real data without letting the user even know
>
Heres a simple example of Optimistic Updates:
```dart
MutationBuilder<Map, String>(
job: newUsernameMutation,
onMutate: (value) {
// getting the query that needs to be updated optimistically
QueryBowl.of(context)
.setQueryData<UserData, void>(job.queryKey, (oldData) {
oldData.name = value;
// you've to return a new instance of the oldData else fl-query
// will assume data hasn't been updated thus won't trigger any changes
return UserData.from(oldData);
});
},
onData: (data){
// replacing the predicted fake data with real data
QueryBowl.of(context)
.setQueryData<UserData, void>(job.queryKey, (oldData) {
oldData.name = data["name"];
// you've to return a new instance of the oldData else fl-query
// will assume data hasn't been updated thus won't trigger any changes
return UserData.from(oldData);
});
}
builder: (context, mutation){
....
....
....
}
);
```
This is all for Mutations. To learn more about Mutation [read the docs](https://fl-query.vercel.app/docs/basics/MutationJob)
## Hooks
Fl-Query supports both Vanilla Flutter & flutter_hooks. Both arent much different everything is same but in fl_query_hooks you additionally get 2 hooks `useQuery` & `useMutation` which you can use in place of `QueryBuilder` & `MutationBuilder`.
### useQuery
It is basically `QueryBuilder` without all the typical Builder boilerplate. So when I write the 1st example with hooks itll look like this:
```dart
class BasicHookExample extends HookWidget {
const BasicHookExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final query = useQuery(job: successJob, externalData: null);
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();
},
), // Text
],
); // Row
}
}
```
### useMutation
I guess, you know what `useMutation` does. Its a replacement for `MutationBuilder` for flutter_hooks which makes code more clean & easier to read
Heres a `useMutation` example:
```dart
Widget build(context){
// the mutation object is the same passed as
// parameter in the builder method of MutationBuilder
final mutation = useMutation(job);
return /* .... (Imaginary Form) */;
}
```
This article only covers simple & most used features of Fl-Query. There are tons of more things that we can do with Fl-Query. Everything is available in the [official docs](https://fl-query.vercel.app/) which is a WIP. So you can contribute to that if you want. Itll really help the project to move forward
> Fl-Query is still under heavy development & it is expected to have bugs + unintended behavior. So if you find any please [create an Issue](https://github.com/KRTirtho/fl-query/issues) with proper details. Also, were open for any suggestions. Suggest what you like or not or want Fl-Query to have. Probably contribute to the project with your own code & feature. It will be much appreciated
> Since the project is in a very early stage it needs appropriate tests & Im the worst excuse for Tester so Fl-Query needs some good testers whore willing to contribute to the project with tests. If you want to contribute with tests. Please [join the discussion](https://github.com/KRTirtho/fl-query/discussions/categories/testing) by creating one
Give Fl-Query a ⭐Star⭐ in [Github](https://github.com/KRTirtho/fl-query)
## Social
Follow me on:
- [Twitter](http://twitter.com/@KrTirtho)
- [LinkedIn](https://www.linkedin.com/in/kingkor-roy-tirtho-810b951b4/)
- [Github](https://github.com/KRTirtho)
- [DEVCommunity](http://dev.to/KRTirtho)
- [Medium](http://medium.com/@krtirtho)
+5 -17
View File
@@ -1,17 +1,5 @@
endi: krtirtho:
name: Endilie Yacop Sucipto name: Kingkor Roy Tirtho
title: Maintainer of Docusaurus title: Creator of Fl-Query
url: https://github.com/endiliey url: https://github.com/KRTirtho
image_url: https://github.com/endiliey.png image_url: https://github.com/KRTirtho.png
yangshun:
name: Yangshun Tay
title: Front End Engineer @ Facebook
url: https://github.com/yangshun
image_url: https://github.com/yangshun.png
slorber:
name: Sébastien Lorber
title: Docusaurus maintainer
url: https://sebastienlorber.com
image_url: https://github.com/slorber.png
+22
View File
@@ -2,3 +2,25 @@
title: Mutation Job title: Mutation Job
sidebar_position: 5 sidebar_position: 5
--- ---
`MutationJob` is just like [`QueryJob`](/docs/basics/QueryJob) but for `Mutations`.
It is used to define how & where the new data is inserted or existing data is updated or deleted. Basically, it's the kind of Job that you'll use with http `POST/PUT/DELETE` requests but it doesn't have to be just HTTP requests, it can be anything that returns as long as it returns Future
Here's a simple example:
```dart
final basicMutationJob = MutationJob<Map, Map<String, dynamic>>(
mutationKey: "basic-mutation-example",
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);
},
);
```
Here, instead of a `queryKey` there's a `mutationKey` parameter that is used to identify the Job.
`Mutation` also supports _retries_ but instead of `externalData` `Mutations` has `variables` parameter that used when the `mutate` method of Mutation is called where you can pass outside data to the `Mutation.task`
+7 -2
View File
@@ -1,5 +1,10 @@
name: fl-query name: fl-query
packages: packages:
- packages/fl_query_hooks - packages/**
- packages/fl_query
ignore:
- package/example/
ide:
intellij: false
@@ -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.5/","native_build":true,"dependencies":[]}],"android":[{"name":"connectivity_plus","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.5/","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":[]}],"linux":[{"name":"connectivity_plus_linux","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/","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":[]}],"web":[{"name":"connectivity_plus_web","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.2/","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":[]}],"date_created":"2022-07-08 03:37:22.314541","version":"3.0.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.5/","native_build":true,"dependencies":[]}],"android":[{"name":"connectivity_plus","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.5/","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":[]}],"linux":[{"name":"connectivity_plus_linux","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/","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":[]}],"web":[{"name":"connectivity_plus_web","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.2/","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":[]}],"date_created":"2022-07-18 18:16:02.735188","version":"3.0.1"}
@@ -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.5/","native_build":true,"dependencies":[]}],"android":[{"name":"connectivity_plus","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.5/","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":[]}],"linux":[{"name":"connectivity_plus_linux","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/","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":[]}],"web":[{"name":"connectivity_plus_web","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.2/","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":[]}],"date_created":"2022-07-12 03:10:11.860962","version":"3.0.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.5/","native_build":true,"dependencies":[]}],"android":[{"name":"connectivity_plus","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.5/","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":[]}],"linux":[{"name":"connectivity_plus_linux","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/","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":[]}],"web":[{"name":"connectivity_plus_web","path":"/home/krtirtho/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.2/","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":[]}],"date_created":"2022-07-18 18:16:00.627101","version":"3.0.1"}