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/cookbook/index.md
+3-3
Original file line number
Diff line number
Diff line change
@@ -1,12 +1,12 @@
1
1
# What is the Cookbook
2
2
3
-
Here are some recipes that you may find useful. If you find a usecase that is missing, you can check if it isn't yet on [the roadmap](https://github.com/vuejs/vuefire/issues/145) or open an issue. You could also directly open a Pull request, but I recommend you to open an issue first so you don't end up wasting your time writing something that won't get published.
3
+
Here are some recipes that you may find useful. If you find a use-case that is missing, you can check if it isn't yet on [the roadmap](https://github.com/vuejs/vuefire/issues/145) or open an issue. You could also directly open a Pull request, but I recommend you to open an issue first so you don't end up wasting your time writing something that won't get published.
4
4
5
5
## Recipes
6
6
7
-
-[Prototyping](./prototyping.md)
8
-
-[Using Firebase Database and Firestore together](./rtdb-and-firestore.md)
7
+
-[Migration from VueFire 2](./migration-v2-v3.md)
9
8
-[Vuex](./vuex.md)
9
+
-[Binding to existing refs](./subscriptions-external.md)
Copy file name to clipboardExpand all lines: docs/cookbook/subscriptions-external.md
+1-1
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ When passing a target ref, the composable will not create a new `ref()` for you,
11
11
12
12
## Pinia
13
13
14
-
If you are using [Pinia](https://pinia.vuejs.org), you can directly use the `useCollection` function within [setup stores](https://pinia.vuejs.org/cookbook/composables.html#setup-stores):
14
+
If you are using [Pinia](https://pinia.vuejs.org), you can directly use the `useCollection()` function within [setup stores](https://pinia.vuejs.org/cookbook/composables.html#setup-stores):
Copy file name to clipboardExpand all lines: docs/guide/auth.md
+11-1
Original file line number
Diff line number
Diff line change
@@ -18,7 +18,17 @@ app.use(VueFire, {
18
18
})
19
19
```
20
20
21
-
This will automatically create and inject the [Auth module](https://firebase.google.com/docs/auth/web/start#add-initialize-sdk) from Firebase so you can access it from within any component with the `useFirebaseAuth()` composable.
21
+
This will automatically initialize and inject the [Auth module](https://firebase.google.com/docs/auth/web/start#add-initialize-sdk) as well as the other features described in this page.
22
+
23
+
## Auth instance
24
+
25
+
You can access the current Auth instance in any component with the `useFirebaseAuth()` composable:
Changing these options will affect all calls to `useDocument()`, `useDatabaseObject()`, ... in your application **and the Options API usage** as well (`$firestoreBind()`, `$rtdbBind()`).
21
+
Changing these options will affect **all calls** to `useDocument()`, `useDatabaseObject()`, ... in your application **as well as Options API calls** (`$firestoreBind()`, `$rtdbBind()`).
22
22
23
-
In both scenarios, **you need to make sure the returned objects contain their original `id`** so other VueFire functionalities can work correctly. The easies way to do this is by reusing the default `serialize`/`converter`:
23
+
## Custom `serialize`/`converter`
24
+
25
+
When adapting `serialize`/`converter` or using `.withConverter()`, **you need to make sure the returned objects contain their original `id`** so other VueFire functionalities can work correctly. The easies way to do this is by reusing the default `serialize`/`converter`:
Copy file name to clipboardExpand all lines: docs/guide/options-api-realtime-data.md
+9-8
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
# Options API Realtime Data
2
2
3
3
::: tip
4
-
This pages assumes you have read the [Realtime Data](./realtime-data.md) page and will only cover the syntax differences between the Options API and the Composition API.
4
+
This pages assumes you have read the [Realtime Data](./realtime-data.md) page and only covers the syntax differences between the Options API and the Composition API.
5
5
:::
6
6
7
7
There are two ways of using Realtime Data with VueFire:
@@ -28,18 +28,18 @@ app.use(VueFire, {
28
28
})
29
29
```
30
30
31
-
You can pass global options to the modules but note **these options are limited to the Options API usage**.They do not affect composition API calls such as `useDocument()` and `useDatabaseObject()`. [Check the global options](./global-options.md) to see how you can override those.
31
+
You can pass global options to the modules but note **these options only affect the Options API usage**.They do not affect composition API calls such as `useDocument()` and `useDatabaseObject()`. [Check the global options](./global-options.md) to see how you can override those.
32
32
33
33
```ts
34
34
app.use(VueFire, {
35
35
modules: [
36
36
VueFireFirestoreOptionsAPI({
37
-
// same behavior as vuefire v2
37
+
//this would be the same behavior as VueFire v2
38
38
reset: true,
39
39
wait: false,
40
40
}),
41
41
VueFireDatabaseOptionsAPI({
42
-
// same behavior as vuefire v2
42
+
//this would be the same behavior as VueFire v2
43
43
reset: true,
44
44
wait: false,
45
45
}),
@@ -49,7 +49,7 @@ app.use(VueFire, {
49
49
50
50
## Declarative binding
51
51
52
-
Any Database Reference provided in a `firebase`/`firestore` option will be bound at creation (after Vue's `beforeMount` hook) to the specified key on the component. In the following example we bind a Collection of Documents to our `documents` property. The key provided in the `firebase`/`firestore` option (`documents`) must be initialized in the `data` of the component:
52
+
Any Database Reference provided in a `firebase`/`firestore` option will be bound at creation (after Vue's `beforeMount` hook) to the specified key on the component. In the following example we bind a _collection_ of Documents to our `documents` property. The key provided in the `firebase`/`firestore` option (`documents`) must be initialized in the `data` of the component:
53
53
54
54
<FirebaseExample>
55
55
@@ -60,6 +60,7 @@ import { ref as dbRef } from 'firebase/database'
60
60
exportdefault {
61
61
data() {
62
62
return {
63
+
// must be an empty array to be bound as a list
63
64
documents: [],
64
65
}
65
66
},
@@ -90,7 +91,7 @@ export default {
90
91
</FirebaseExample>
91
92
92
93
::: warning
93
-
You must declare properties with their initial values in `data`. **For the RTDB, using an _Array_ as the initial value will bind the Reference as an array, otherwise it is bound as an object**. For Firestore, collections and queries are bound as arrays while documents are bound as objects.
94
+
You must declare properties with their initial values in `data`. **For Firebase Database, using an _Array_ as the initial value will bind the Reference as an array, otherwise it will be bound as an object**. For Firestore, collections and queries are bound as arrays while documents are bound as objects.
While VueFire will automatically unbind any reference bound in a component whenever needed, you may still want to do it on your own to stop displaying updates on a document or collection or because the user logged out and they do not have read-access to a resource anymore.
193
+
While VueFire will automatically unbind any reference bound in a component whenever needed, you may still want to do it on your own to stop displaying updates on a document or collection or because the user logged out and they do not have the permissions anymore.
These composables all return a Vue `Ref`of the data. Note **this is a readonly data**, you shouldn't mutate it directly, [use the Firebase SDK](./writing-data.md) instead. It will be automatically updated when the data changes anywhere.
55
+
These composables all a Vue `Ref`containing the data. Note **this is a readonly data**, you shouldn't mutate it directly, you should instead [use the Firebase SDK](./writing-data.md). VueFire will automatically keep the data in sync with the database.
56
56
57
-
Sometimes, you need to change the document you are observing, let's say you have a list of contacts and that you display one based on the URL, you handle this by passing a reactive variable of the data source to the `useDocument()`, `useDatabaseObject()`, etc composables:
57
+
Sometimes, you need to start observing a different document or collection, let's say you have a _collection_ of contacts and that you display a specific contact based on the URL, e.g. displaying the contact with an id equal to `24` on `/contacts/24`, you can achieve this this by passing a _reactive variable of the data source_ to the `useDocument()`, `useDatabaseObject()`, etc composables:
58
+
59
+
<FirebaseExample>
60
+
61
+
```ts
62
+
const route =useRoute()
63
+
// since route is reactive, `contactSource` will be reactive too
64
+
const contactSource =computed(
65
+
() =>dbRef(db, 'contacts/'+route.params.id)
66
+
)
67
+
// contact will always be in sync with the data source
68
+
const contact =useDatabaseObject(contactSource)
69
+
```
58
70
59
71
```ts
60
72
const route =useRoute()
73
+
// since route is reactive, `contactSource` will be reactive too
// contact will always be in sync with the data source
65
78
const contact =useDocument(contactSource)
66
79
```
67
80
68
-
This way, if the route changes, the document will be updated to the new one, automatically unsubscribing from the previous one and subscribing to the new one.
81
+
</FirebaseExample>
82
+
83
+
This way, when the route changes, the document will be updated to the new one, automatically unsubscribing from the previous one and subscribing to the new one.
69
84
70
85
::: tip
71
-
If you can't use a `computed()`, use `shallowRef()`s instead of `ref()`s to store the data sources. This is because `shallowRef()` doesn't try to recursively observe the object it's given, which in the case of a Firebase data source, would be wasteful.
86
+
If you can't use a `computed()`, use `shallowRef()`s instead of `ref()`s to store the data sources. This is because `shallowRef()` doesn't try to recursively observe the object it's given, which in the case of a Firebase data source, would be worse in terms of performance.
72
87
:::
73
88
74
89
### Subscription state
75
90
76
-
All of the composables not only return a `Ref`, they can also be destructured to access other useful data like _is the initial load still pending?_ or _did the subscription fail?_. You only need to destructure the returned value from the composables:
91
+
All of the composables can also be destructured to access other useful data like _is the initial load still pending?_ or _did the subscription fail?_. You only need to destructure the returned value from the composables:
77
92
78
93
```ts
79
94
// instead of writing
@@ -91,19 +106,19 @@ const {
91
106
} =useDocument(contactSource)
92
107
```
93
108
94
-
Notice how we rename `data` to whatever makes more sense for the context. It's important to note
109
+
Notice how we rename `data` to whatever makes more sense for the context.
95
110
96
111
::: warning
97
-
All of the properties that can be defined on the Ref are defined as [non-enumerable properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) which means they won't be copied over when using the spread operator e.g. `const { data, ...rest } = useDocument(contactSource)`. This is to ensure they are completely ignored in other places like devtools.
112
+
All of the properties that can be defined on the `Ref` are defined as [non-enumerable properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) which means they won't be copied over when using the spread operator e.g. `const { data, ...rest } = useDocument(contactSource)`. This is to ensure they are completely ignored and do not cerate problems in other places like devtools.
98
113
:::
99
114
100
-
## VueFire extras
115
+
## VueFire additions
101
116
102
117
VueFire adds a few properties to the data snapshot to make it easier to work with.
103
118
104
119
### Document's `id`
105
120
106
-
Each document/object, has an `id` property that is the key of the document/object. This is useful when you want to display the id of the document/object in your template. It's set as a non enumerable property so it won't be copied over when using the spread operator.
121
+
Each document/object, has an convenient `id` property that is the id/key of the document/object. It's set as a non enumerable property so it won't be copied over when using the spread operator.
This behavior can be customized through the [`serialize`/`converter` option](./global-options.md#custom-serializeconverter). Note that in both cases, **you must keep the `id` property for VueFire to correctly work**.
148
+
132
149
### GeoPoints (Firestore only)
133
150
134
151
In Firestore you can store [GeoPoints](https://firebase.google.com/docs/reference/js/firestore_.geopoint). They are retrieved as-is by VueFire, meaning that you can directly use methods like `isEqual` and access its properties `latitude` and `longitude`.
Note this is only a type annotation, it does not perform any runtime validation.
315
+
Note this is only a type annotation, it does not perform any runtime validation. If you want a runtime validation, you can use the `withConverter()` method as shown below.
297
316
298
317
### Firestore `.withConverter()`
299
318
@@ -304,6 +323,8 @@ The recommended Firebase approach is to use the `withConverter()` for Firestore:
Copy file name to clipboardExpand all lines: docs/guide/ssr.md
+22-22
Original file line number
Diff line number
Diff line change
@@ -98,6 +98,27 @@ Web Security is a broad topic that we cannot cover here. We recommend you to rea
98
98
-[State Serialization in vite-ssg](https://github.com/antfu/vite-ssg#state-serialization)
99
99
-[SSR Best practices for Vue.js](https://vuejs.org/guide/best-practices/security.html#server-side-rendering-ssr)
100
100
101
+
## Manual SSR keys
102
+
103
+
VueFire automatically infers an SSR key based on the path of the document or collection whenever possible. This means there are some scenarios where **you have to provide a manual `ssrKey`**:
104
+
105
+
- When using Firestore Queries
106
+
- When binding the same document multiple times
107
+
108
+
In these scenarios, provide the `ssrKey` as a second argument to `useDocument()`, `useCollection()`, etc:
109
+
110
+
<FirebaseExample>
111
+
112
+
```ts
113
+
useDatabaseList(queryRef, { ssrKey: 'my-quiz' })
114
+
```
115
+
116
+
```ts
117
+
useCollection(queryRef, { ssrKey: 'my-quiz' })
118
+
```
119
+
120
+
</FirebaseExample>
121
+
101
122
## Usage outside of components
102
123
103
124
If you are using VueFire composables outside of components, e.g. using `useDocument()` within a [Pinia](https://pinia.vuejs.org) store, you need to manually wait for the data to be loaded on the server as VueFire cannot call `onServerPrefetch()` for you and you will have to manually call it yourself. VueFire exposes a function to retrieve all pending promises created by the different composables (`useDocument()`, `useDatabaseObject()`, etc). You will need to use it inside of **any component that uses the data**:
While the recommended approach is to use `onServerPrefetch()`, aother possibility is to [use `<Suspense>`](https://vuejs.org/guide/built-ins/suspense.html#suspense) to be able to use `await` within `setup()`:
139
+
While the recommended approach is to use `onServerPrefetch()`, another possibility is to [use `<Suspense>`](https://vuejs.org/guide/built-ins/suspense.html#suspense) to be able to use `await` within `setup()`:
VueFire automatically infers an SSR key based on the path of the document or collection whenever possible. This means there are some scenarios where **you have to provide a manual `ssrKey`**:
172
-
173
-
- When using Firestore Queries
174
-
- When binding the same document multiple times
175
-
176
-
In these scenarios, provide the `ssrKey` as a second argument to `useDocument()`, `useCollection()`, etc:
0 commit comments