docs: add advanced category, move optimistic updates & persisting queries to advanced
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Optimistic Updates
|
||||
sidebar_position: 10
|
||||
sidebar_position: 1
|
||||
---
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
@@ -0,0 +1,128 @@
|
||||
---
|
||||
title: Persisting Queries
|
||||
sidebar_position: 1
|
||||
---
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
Implementing offline capabilites by your own can be hard to do (and maintain!!) so Fl-Query makes easier for developers to do it. Fl-Query uses [Hive](https://docs.hivedb.dev/#/) to persist queries to disk. Hive is a Open Source, "lightweight and buzzing-fast key-value database made for Flutter and Dart."
|
||||
|
||||
We're using hive because it supports storing unstructured data and the write speed is blazingly fast
|
||||
|
||||
But it is planned to support multiple types of Database for persisting using an Adapter pattern
|
||||
|
||||
### Persisting Queries
|
||||
|
||||
Queries can be persisted by passing `jsonConfig` argument to the `QueryBuilder` or `useQuery`. Persisted queries are stored in [hive](https://docs.hivedb.dev/) cache and are available even after the app is restarted
|
||||
|
||||
First make sure your custom data type is json serializable. You can use [json_serializable](https://pub.dev/packages/json_serializable) package to generate `toJson` and `fromJson` methods for your data type
|
||||
|
||||
|
||||
```dart
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'todo.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class Todo{
|
||||
final String id;
|
||||
final String title;
|
||||
final bool completed;
|
||||
|
||||
Todo({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.completed,
|
||||
});
|
||||
|
||||
factory Todo.fromJson(Map<String, dynamic> json) => _$TodoFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$TodoToJson(this);
|
||||
}
|
||||
```
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="vanilla" label="Vanilla">
|
||||
|
||||
```dart
|
||||
QueryBuilder<Todo, HttpException>(
|
||||
"todos",
|
||||
() => api.getTodos(),
|
||||
jsonConfig: JsonConfig(
|
||||
fromJson: (json) => Todo.fromJson(json),
|
||||
toJson: (todo) => todo.toJson(),
|
||||
),
|
||||
builder: (context, query) {
|
||||
/* ... */
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="flutter_hooks" label="Flutter Hooks">
|
||||
|
||||
```dart
|
||||
useQuery<Todo, HttpException>(
|
||||
"todos",
|
||||
() => api.getTodos(),
|
||||
jsonConfig: JsonConfig(
|
||||
fromJson: (json) => Todo.fromJson(json),
|
||||
toJson: (todo) => todo.toJson(),
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Right now due to lack of reflection support and compile time macros we're unable to serialize any data type on the fly.
|
||||
That's why `JsonConfig` is required. Otherwise, a simple `persistToDisk: true` would have been enough
|
||||
|
||||
### Persisting InfiniteQueries
|
||||
|
||||
Just like `Query`, `InfiniteQuery` also accepts `jsonConfig` argument to persist page data to disk. With persisting `InfiniteQuery` you can achieve similar results like facebook/twitter's offline mode
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="vanilla" label="Vanilla">
|
||||
|
||||
```dart
|
||||
InfiniteQueryBuilder<PagedPosts, ClientException, int>(
|
||||
"posts",
|
||||
(page) => api.getPostsPaginated(page),
|
||||
nextPage: (lastPage, lastPageData) {
|
||||
/// returning [null] will set [hasNextPage] to [false]
|
||||
if (lastPageData.posts.length < 10) return null;
|
||||
return lastPage + 1;
|
||||
},
|
||||
initialPage: 0,
|
||||
jsonConfig: JsonConfig(
|
||||
fromJson: (json)=> PagedPosts.fromJson(json),
|
||||
toJson: (pagedPosts) => pagedPosts.toJson(),
|
||||
),
|
||||
builder: /*...*/
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="flutter_hooks" label="Flutter Hooks">
|
||||
|
||||
```dart
|
||||
final query = useInfiniteQuery<PagedPosts, ClientException, int>(
|
||||
"posts",
|
||||
(page) => api.getPostsPaginated(page),
|
||||
nextPage: (lastPage, lastPageData) {
|
||||
/// returning [null] will set [hasNextPage] to [false]
|
||||
if (lastPageData.posts.length < 10) return null;
|
||||
return lastPage + 1;
|
||||
},
|
||||
initialPage: 0,
|
||||
jsonConfig: JsonConfig(
|
||||
fromJson: (json)=> PagedPosts.fromJson(json),
|
||||
toJson: (pagedPosts) => pagedPosts.toJson(),
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This will persist each available page to a HiveStore
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "Advanced",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Advanced caching and data manipulation techniques to make your app better"
|
||||
}
|
||||
}
|
||||
@@ -217,7 +217,7 @@ await Future.wait(
|
||||
|
||||
### Set page data manually
|
||||
|
||||
`InfiniteQuery` provides a method `InfiniteQuery.setPageData` to set page data manually. This can be useful if you want to set data after a mutation for [Optmisitc Updates](/docs/basics/OptimisticUpdates)
|
||||
`InfiniteQuery` provides a method `InfiniteQuery.setPageData` to set page data manually. This can be useful if you want to set data after a mutation for [Optmisitc Updates](/docs/advanced/OptimisticUpdates)
|
||||
|
||||
```dart
|
||||
query.setPageData(0, [...query.pages[0], newProduct])
|
||||
@@ -309,56 +309,4 @@ final query = useInfiniteQuery<PagedProducts, ClientException, int>(
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Persisting InfiniteQueries
|
||||
|
||||
The `pages` data can be saved to disk to be loaded next time when the app starts to reduce loading time of your app. Just like [`Query`](/docs/basics/Queries#persisting-queries) persisted `InfiniteQuery`'s `pages` data are stored in [hive](https://docs.hivedb.dev/#/). This can be widely useful to add offline capabilities to the app
|
||||
|
||||
For this you need to pass a `jsonConfig: JsonConfig()` argument to `InfiniteQueryBuilder` or `useInfiniteQuery`. Also make sure your `DataType` is serializable to JSON. You can use [json_serializable](https://pub.dev/packages/json_serializable) to generate the code for you.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="vanilla" label="Vanilla">
|
||||
|
||||
```dart
|
||||
InfiniteQueryBuilder<PagedPosts, ClientException, int>(
|
||||
"posts",
|
||||
(page) => api.getPostsPaginated(page),
|
||||
nextPage: (lastPage, lastPageData) {
|
||||
/// returning [null] will set [hasNextPage] to [false]
|
||||
if (lastPageData.posts.length < 10) return null;
|
||||
return lastPage + 1;
|
||||
},
|
||||
initialPage: 0,
|
||||
jsonConfig: JsonConfig(
|
||||
fromJson: (json)=> PagedPosts.fromJson(json),
|
||||
toJson: (pagedPosts) => pagedPosts.toJson(),
|
||||
),
|
||||
builder: /*...*/
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="flutter_hooks" label="Flutter Hooks">
|
||||
|
||||
```dart
|
||||
final query = useInfiniteQuery<PagedPosts, ClientException, int>(
|
||||
"posts",
|
||||
(page) => api.getPostsPaginated(page),
|
||||
nextPage: (lastPage, lastPageData) {
|
||||
/// returning [null] will set [hasNextPage] to [false]
|
||||
if (lastPageData.posts.length < 10) return null;
|
||||
return lastPage + 1;
|
||||
},
|
||||
initialPage: 0,
|
||||
jsonConfig: JsonConfig(
|
||||
fromJson: (json)=> PagedPosts.fromJson(json),
|
||||
toJson: (pagedPosts) => pagedPosts.toJson(),
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This will persist each available page to a HiveStore
|
||||
</Tabs>
|
||||
@@ -133,7 +133,7 @@ final mutation = useMutation<Map<String, dynamic>, dynamic, Map<String, dynamic>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
> Learn how to use `onMutate` & `Query.setData` to implement [optimistic updates](/docs/basics/OptimisticUpdates)
|
||||
> Learn how to use `onMutate` & `Query.setData` to implement [optimistic updates](/docs/advanced/OptimisticUpdates)
|
||||
|
||||
### Refetch Queries and InfiniteQueries on successful mutation
|
||||
|
||||
|
||||
@@ -190,70 +190,4 @@ useQuery<String, HttpException>(
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Now these queries won't be executed as soon as they're mounted. Until `Query.refresh()` or `Query.fetch()` is called these will stay in initial state. If `initial` data was passed, it'll be used until the query is refreshed. Same goes for persisting queries
|
||||
|
||||
### Persisting Queries
|
||||
|
||||
Queries can be persisted by passing `jsonConfig` argument to the `QueryBuilder` or `useQuery`. Persisted queries are stored in [hive](https://docs.hivedb.dev/) cache and are available even after the app is restarted
|
||||
|
||||
First make sure your custom data type is json serializable. You can use [json_serializable](https://pub.dev/packages/json_serializable) package to generate `toJson` and `fromJson` methods for your data type
|
||||
|
||||
|
||||
```dart
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'todo.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class Todo{
|
||||
final String id;
|
||||
final String title;
|
||||
final bool completed;
|
||||
|
||||
Todo({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.completed,
|
||||
});
|
||||
|
||||
factory Todo.fromJson(Map<String, dynamic> json) => _$TodoFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$TodoToJson(this);
|
||||
}
|
||||
```
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="vanilla" label="Vanilla">
|
||||
|
||||
```dart
|
||||
QueryBuilder<Todo, HttpException>(
|
||||
"todos",
|
||||
() => api.getTodos(),
|
||||
jsonConfig: JsonConfig(
|
||||
fromJson: (json) => Todo.fromJson(json),
|
||||
toJson: (todo) => todo.toJson(),
|
||||
),
|
||||
builder: (context, query) {
|
||||
/* ... */
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="flutter_hooks" label="Flutter Hooks">
|
||||
|
||||
```dart
|
||||
useQuery<Todo, HttpException>(
|
||||
"todos",
|
||||
() => api.getTodos(),
|
||||
jsonConfig: JsonConfig(
|
||||
fromJson: (json) => Todo.fromJson(json),
|
||||
toJson: (todo) => todo.toJson(),
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Right now due to lack of reflection support and compile time macros we're unable to serialize any data type on the fly.
|
||||
That's why `JsonConfig` is required. Otherwise, a simple `persistToDisk: true` would have been enough
|
||||
Now these queries won't be executed as soon as they're mounted. Until `Query.refresh()` or `Query.fetch()` is called these will stay in initial state. If `initial` data was passed, it'll be used until the query is refreshed. Same goes for persisting queries
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"label": "Basics",
|
||||
"position": 3,
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Learn all the basic concepts of Fl-Query as well as the practical use-cases that can enhance your development experience"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"label": "Getting Started",
|
||||
"position": 1,
|
||||
"position": 1,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: Overview
|
||||
id: overview
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Asynchronous data caching, refetching & invalidation library for Flutter. FL-Query lets you manage & distribute your async data without touching any global state
|
||||
|
||||
Fl-Query makes asynchronous server state management a breeze in flutter
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"label": "Tutorial - Extras",
|
||||
"position": 4,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB |
@@ -1,55 +0,0 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Manage Docs Versions
|
||||
|
||||
Docusaurus can manage multiple versions of your docs.
|
||||
|
||||
## Create a docs version
|
||||
|
||||
Release a version 1.0 of your project:
|
||||
|
||||
```bash
|
||||
npm run docusaurus docs:version 1.0
|
||||
```
|
||||
|
||||
The `docs` folder is copied into `versioned_docs/version-1.0` and `versions.json` is created.
|
||||
|
||||
Your docs now have 2 versions:
|
||||
|
||||
- `1.0` at `http://localhost:3000/docs/` for the version 1.0 docs
|
||||
- `current` at `http://localhost:3000/docs/next/` for the **upcoming, unreleased docs**
|
||||
|
||||
## Add a Version Dropdown
|
||||
|
||||
To navigate seamlessly across versions, add a version dropdown.
|
||||
|
||||
Modify the `docusaurus.config.js` file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
// highlight-start
|
||||
{
|
||||
type: 'docsVersionDropdown',
|
||||
},
|
||||
// highlight-end
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
The docs version dropdown appears in your navbar:
|
||||
|
||||

|
||||
|
||||
## Update an existing version
|
||||
|
||||
It is possible to edit versioned docs in their respective folder:
|
||||
|
||||
- `versioned_docs/version-1.0/hello.md` updates `http://localhost:3000/docs/hello`
|
||||
- `docs/hello.md` updates `http://localhost:3000/docs/next/hello`
|
||||
@@ -1,88 +0,0 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Translate your site
|
||||
|
||||
Let's translate `docs/intro.md` to French.
|
||||
|
||||
## Configure i18n
|
||||
|
||||
Modify `docusaurus.config.js` to add support for the `fr` locale:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'fr'],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Translate a doc
|
||||
|
||||
Copy the `docs/intro.md` file to the `i18n/fr` folder:
|
||||
|
||||
```bash
|
||||
mkdir -p i18n/fr/docusaurus-plugin-content-docs/current/
|
||||
|
||||
cp docs/intro.md i18n/fr/docusaurus-plugin-content-docs/current/intro.md
|
||||
```
|
||||
|
||||
Translate `i18n/fr/docusaurus-plugin-content-docs/current/intro.md` in French.
|
||||
|
||||
## Start your localized site
|
||||
|
||||
Start your site on the French locale:
|
||||
|
||||
```bash
|
||||
npm run start -- --locale fr
|
||||
```
|
||||
|
||||
Your localized site is accessible at `http://localhost:3000/fr/` and the `Getting Started` page is translated.
|
||||
|
||||
:::caution
|
||||
|
||||
In development, you can only use one locale at a same time.
|
||||
|
||||
:::
|
||||
|
||||
## Add a Locale Dropdown
|
||||
|
||||
To navigate seamlessly across languages, add a locale dropdown.
|
||||
|
||||
Modify the `docusaurus.config.js` file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
// highlight-start
|
||||
{
|
||||
type: 'localeDropdown',
|
||||
},
|
||||
// highlight-end
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
The locale dropdown now appears in your navbar:
|
||||
|
||||

|
||||
|
||||
## Build your localized site
|
||||
|
||||
Build your site for a specific locale:
|
||||
|
||||
```bash
|
||||
npm run build -- --locale fr
|
||||
```
|
||||
|
||||
Or build your site to include all the locales at once:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
Reference in New Issue
Block a user