feat(nuxt): deep watch useCookie ref value by default (#9664)

* feat(nuxt): useCookie add deep watch option

* docs(api): useCookie add deepWatch option

* feat(nuxt): useCookie change deepWatch to watch option

* boolean|shallow

* enable watch by default

* docs: fix example

* docs(api): update useCookie example

Co-authored-by: Pooya Parsa <pooya@pi0.io>
Co-authored-by: Daniel Roe <daniel@roe.dev>
This commit is contained in:
Mehdi HosseinZade 2022-12-19 15:20:46 +03:30 committed by GitHub
parent c0be933b02
commit 04c8625843
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 11 deletions

View File

@ -26,15 +26,9 @@ The example below creates a cookie called `counter`. If the cookie doesn't exist
<template>
<div>
<h1>Counter: {{ counter || '-' }}</h1>
<button @click="counter = null">
reset
</button>
<button @click="counter--">
-
</button>
<button @click="counter++">
+
</button>
<button @click="counter = null">reset</button>
<button @click="counter--">-</button>
<button @click="counter++">+</button>
</div>
</template>
@ -138,6 +132,71 @@ be returned as the cookie's value.
Specifies a function that returns the cookie's default value. The function can also return a `Ref`.
### `watch`
Specifies the `boolean` or `string` value for [watch](https://vuejs.org/api/reactivity-core.html#watch) cookie ref data.
- `true` - Will watch cookie ref data changes and its nested properties. (default)
- `shallow` - Will watch cookie ref data changes for only top level properties
- `false` Will not watch cookie ref data changes.
**Example 1:**
```vue
<template>
<div>User score: {{ user?.score }}</div>
</template>
<script setup>
const user = useCookie(
'userInfo',
{
default: () => ({ score: -1 }),
watch: false
}
)
if (user.value && user.value !== null) {
user.value.score++; // userInfo cookie not update with this change
}
</script>
```
**Example 2:**
```vue
<template>
<div>
<h1>List</h1>
<pre>{{ list }}</pre>
<button @click="add">Add</button>
<button @click="save">Save</button>
</div>
</template>
<script setup>
const list = useCookie(
'list',
{
default: () => [],
watch: 'shallow'
}
)
function add() {
list.value?.push(Math.round(Math.random() * 1000))
// list cookie not update with this change
}
function save() {
if (list.value && list.value !== null) {
list.value = [...list.value]
// list cookie update with this change
}
}
</script>
```
## Handling Cookies in API Routes
You can use `getCookie` and `setCookie` from [`h3`](https://github.com/unjs/h3) package to set cookies in server API routes.

View File

@ -15,12 +15,14 @@ export interface CookieOptions<T = any> extends _CookieOptions {
decode?(value: string): T
encode?(value: T): string
default?: () => T | Ref<T>
watch?: boolean | 'shallow'
}
export interface CookieRef<T> extends Ref<T> {}
const CookieDefaults: CookieOptions<any> = {
path: '/',
watch: true,
decode: val => destr(decodeURIComponent(val)),
encode: val => encodeURIComponent(typeof val === 'string' ? val : JSON.stringify(val))
}
@ -32,7 +34,12 @@ export function useCookie <T = string | null> (name: string, _opts?: CookieOptio
const cookie = ref<T | undefined>(cookies[name] as any ?? opts.default?.())
if (process.client) {
watch(cookie, () => { writeClientCookie(name, cookie.value, opts as CookieSerializeOptions) })
const callback = () => { writeClientCookie(name, cookie.value, opts as CookieSerializeOptions) }
if (opts.watch) {
watch(cookie, callback, { deep: opts.watch !== 'shallow' })
} else {
callback()
}
} else if (process.server) {
const nuxtApp = useNuxtApp()
const writeFinalCookieValue = () => {