You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/composition-api.md
+86-16Lines changed: 86 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,17 +12,14 @@ Before you can use the `useFind` and `useGet` composition functions, you'll need
12
12
13
13
## useFind <Badgetext="3.0.0+" />
14
14
15
-
If you have already used the `makeFindMixin`, the `useFind` composition function will be very familiar, since it offers the same functionality in a more powerful way. There are a few differences, though.
16
-
17
-
1. Instead of providing a service name, you provide a service Model from the `$FeathersVuex` Vue plugin.
18
-
1. The default behavior of `useFind` is to immediately query the API server. The `makeFindMixin`, by default, would wait until the watcher noticed the change. This is to match the default behavior of `watch` in the Vue Composition API. You can pass `{ lazy: true }` in the `useFind` options, which will be passed directly to the internal `watch` on the params.
19
-
20
-
Note that with the Vue Options API (aka the only way to write components in Vue 2.0) the models are found in `this.$FeathersVuex`. With the Vue Composition API, this object is now at `context.root.$FeathersVuex`, as shown in the following example:
15
+
The `useFind` utility reduces boilerplate for querying with fall-through cache and realtime updates. To get started with it you provide a `model` class and a computed `params` object. Let's use the example of creating a User Guide, where we need to pull in the various `Tutorial` records from our `tutorials` service. We'll keep it simple in the template and just show a list of the names. Assume that each `Tutorial` record has a `name` property. We're not going to style any of this, so the `<style>` tags are removed from the examples.
21
16
22
17
```html
23
18
<template>
24
19
<div>
25
-
<pre> {{ todos }} </pre>
20
+
<liv-for="tutorial in tutorials":key="tutorial._id">
21
+
{{ tutorial.name }}
22
+
</li>
26
23
</div>
27
24
</template>
28
25
@@ -33,27 +30,100 @@ import { useFind } from 'feathers-vuex'
// Provide the model and params to the useFind utility
47
-
const { todos } =useFind({ model: Todo, params: todosParams })
48
-
49
-
return { todos }
42
+
return {
43
+
tutorials:tutorialsData.items
44
+
}
50
45
}
51
46
}
52
47
</script>
48
+
```
49
+
50
+
### Options
51
+
52
+
Let's look at the `UseFindOptions` TypeScript interface to see what else we can pass in the options. If this is your first time, let's do a quick primer for the below interface as an alternative to reading the [TypeScript interface docs](https://www.typescriptlang.org/docs/handbook/interfaces.html):
53
+
54
+
-`UseFindOptions` is the name of the interface, similar to naming any other variable.
55
+
- Each line of the interface documents a property.
56
+
- The string before the `:` is the name of the property.
57
+
- Everything after the `:` describes what type of variable it is.
58
+
- You can look at any `|` after the `:` as a conditional "or"
59
+
- Any property not followed by a `?` is required.
60
+
- Any property followed by a `?` is optional.
61
+
62
+
```ts
63
+
interfaceUseFindOptions {
64
+
model:Function
65
+
params:Params|Ref<Params>
66
+
fetchParams?:Params|Ref<Params>
67
+
queryWhen?:Ref<Function>
68
+
qid?:string
69
+
lazy?:boolean
70
+
}
71
+
```
53
72
54
-
<stylelang="postcss"></style>
73
+
Let's look at each one individually:
74
+
75
+
-`model` must be a Feathers-Vuex Model class. The Model's `find` and `findInStore` methods are used to query data.
76
+
-`params` is a FeathersJS Params object OR a Composition API `ref` (or `computed`, since they return a `ref` instance) which returns a Params object.
77
+
- When provided alone (without the options `fetchParams`), this same query is used for both the local data store and the API requests.
78
+
- Explicitly returning `null` will prevent an API request from being made.
79
+
- You can use `params.qid` to dynamically specify the query identifier for any API request.
80
+
- Set `params.paginate` to `true` to turn off realtime updates for the results and defer pagination to the API server.
81
+
- Set `params.debounce` to an integer and the API requests will automatically be debounced by that many milliseconds. For example, setting `debounce: 1000` will assure that the API request will be made at most every 1 second.
82
+
= `fetchParams` This is a separate set of params that, when provided, will become the params sent to the API server. The `params` will then only be used to query data from the local data store.
83
+
- Explicitly returning `null` will prevent an API request from being made.
84
+
-`queryWhen` must be a `computed` property which returns a `boolean`. It provides a logical separation for preventing API requests *outside* of the `params`.
85
+
-`qid` allows you to specify a query identifier (used in the pagination data in the store). This can also be set dynamically by returning a `qid` in the params.
86
+
-`lazy`, which is `false` by default, determines if the internal `watch` should fire immediately. Set `lazy: true` and the query will not fire immediately. It will only fire on subsequent changes in the params.
87
+
88
+
### Returned Utilities
89
+
90
+
Notice the `tutorialsData` in the previous example. You can see that there's an `items` property, which is returned from the `setup` method as the `tutorials`. There are many more attributes available in the object returned from `useFind`. We can learn more about the return values by looking at its TypeScript interface, below.
91
+
92
+
```ts
93
+
interfaceUseFindData {
94
+
items:Ref<any>
95
+
servicePath:Ref<string>
96
+
isFindPending:Ref<boolean>
97
+
haveBeenRequestedOnce:Ref<boolean>
98
+
haveLoadedOnce:Ref<boolean>
99
+
isLocal:Ref<boolean>
100
+
qid:Ref<string>
101
+
debounceTime:Ref<number>
102
+
latestQuery:Ref<object>
103
+
paginationData:Ref<object>
104
+
error:Ref<Error>
105
+
find:Function
106
+
}
55
107
```
56
108
109
+
Let's look at at what functionality each provides:
110
+
111
+
-`items` is the list of results
112
+
113
+
### Renaming attributes
114
+
115
+
The `useFind` utility will always return an
116
+
They can be renamed in the same way that you would do it with any object.
117
+
118
+
### Compared to `makeFindMixin`
119
+
If you have already used the `makeFindMixin`, the `useFind` composition function will be very familiar, since it offers the same functionality in a more powerful way. There are a few differences, though.
120
+
121
+
1.`useFind` is more TypeScript friendly. Since the mixins depended on adding dynamic attribute names that wouldn't overlap, TypeScript tooling and autocomplete weren't very effective. The attributes returned from `useFind` are always consistent.
122
+
1. Instead of providing a service name, you provide a service Model from the `$FeathersVuex` Vue plugin.
123
+
1. The default behavior of `useFind` is to immediately query the API server. The `makeFindMixin`, by default, would wait until the watcher noticed the change. This is to match the default behavior of `watch` in the Vue Composition API. You can pass `{ lazy: true }` in the `useFind` options, which will be passed directly to the internal `watch` on the params.
124
+
125
+
Note that with the Vue Options API (aka the only way to write components in Vue 2.0) the models are found in `this.$FeathersVuex`. With the Vue Composition API, this object is now at `context.root.$FeathersVuex`, as shown in the following example:
126
+
57
127
Notice in the above example that the params are provided as a computed property. For long-term maintainability, this is the recommended practice. It encourages you to think about your queries declaratively. Think of a declarative query as having all of the instructions it needs to pull in data from whatever sources are required to build the query object. Declaratively written queries will likely assist you in avoiding conflicting code as conditions for making queries become more complex.
58
128
59
129
In contrast, an imperatively-written query would be a reactive object that you directly modify. Think of imperative as pushing information into the query. eg: `params.query.user = props.userId`. When you have a lot of imperative code pushing parameters into the query, it's really easy to create conflicting logic. So keep in mind that while Feathers-Vuex will definitely handle an imperative-style query, your code will probably be less maintainable over the long run.
0 commit comments