fix(nuxt): use addEventListener to register cookie store listener (#28193)

This commit is contained in:
Daniel Roe 2024-07-18 15:52:40 +01:00
parent a6af09eba4
commit 2417848bf2
No known key found for this signature in database
GPG Key ID: CBC814C393D93268
4 changed files with 29 additions and 12 deletions

View File

@ -14,7 +14,8 @@ declare global {
interface Window {
cookieStore?: {
onchange: (event: any) => void
addEventListener: (type: 'change', listener: (event: any) => void) => void
removeEventListener: (type: 'change', listener: (event: any) => void) => void
}
}
}

View File

@ -83,13 +83,16 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
const handleChange = (data: { value?: any, refresh?: boolean }) => {
const value = data.refresh ? readRawCookies(opts)?.[name] : opts.decode(data.value)
watchPaused = true
cookies[name] = cookie.value = value
cookie.value = value
cookies[name] = klona(value)
nextTick(() => { watchPaused = false })
}
let watchPaused = false
if (getCurrentScope()) {
const hasScope = !!getCurrentScope()
if (hasScope) {
onScopeDispose(() => {
watchPaused = true
callback()
@ -98,10 +101,14 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
}
if (store) {
store.onchange = (event) => {
const changeHandler = (event: any) => {
const cookie = event.changed.find((c: any) => c.name === name)
if (cookie) { handleChange({ value: cookie.value }) }
}
store.addEventListener('change', changeHandler)
if (hasScope) {
onScopeDispose(() => store.removeEventListener('change', changeHandler))
}
} else if (channel) {
channel.onmessage = ({ data }) => handleChange(data)
}

View File

@ -589,7 +589,7 @@ describe('nuxt composables', () => {
},
})
const cookies = res.headers.get('set-cookie')
expect(cookies).toMatchInlineSnapshot('"set-in-plugin=true; Path=/, set=set; Path=/, browser-set=set; Path=/, browser-set-to-null=; Max-Age=0; Path=/, browser-set-to-null-with-default=; Max-Age=0; Path=/, browser-object-default=%7B%22foo%22%3A%22bar%22%7D; Path=/"')
expect(cookies).toMatchInlineSnapshot('"set-in-plugin=true; Path=/, accessed-with-default-value=default; Path=/, set=set; Path=/, browser-set=set; Path=/, browser-set-to-null=; Max-Age=0; Path=/, browser-set-to-null-with-default=; Max-Age=0; Path=/, browser-object-default=%7B%22foo%22%3A%22bar%22%7D; Path=/"')
})
it('updates cookies when they are changed', async () => {
const { page } = await renderPage('/cookies')

View File

@ -1,28 +1,37 @@
<script setup>
<script setup lang="ts">
useCookie('accessed-but-not-used')
useCookie('accessed-with-default-value', () => 'default')
useCookie('accessed-with-default-value', { default: () => 'default' })
useCookie('set').value = 'set'
useCookie('set-to-null').value = null
useCookie('set-to-null-with-default', () => 'default').value = null
useCookie<string | null>('set-to-null-with-default', { default: () => 'default' }).value = null
// the next set are all sent by browser
useCookie('browser-accessed-but-not-used')
useCookie('browser-accessed-with-default-value', () => 'default')
useCookie('browser-accessed-with-default-value', { default: () => 'default' })
useCookie('browser-set').value = 'set'
useCookie('browser-set-to-null').value = null
useCookie('browser-set-to-null-with-default', () => 'default').value = null
useCookie<string | null>('browser-set-to-null-with-default', { default: () => 'default' }).value = null
const objectCookie = useCookie('browser-object-default')
const objectCookie = useCookie<{ foo: string } | undefined>('browser-object-default')
const objectCookieSecond = useCookie('browser-object-default', {
default: () => ({ foo: 'bar' }),
})
function changeCookie () {
console.log(objectCookie.value, objectCookieSecond.value)
if (objectCookie.value!.foo === 'baz') {
objectCookie.value!.foo = 'bar'
} else {
objectCookie.value!.foo = 'baz'
}
}
</script>
<template>
<div>
<div>cookies testing page</div>
<pre>{{ objectCookie?.foo }}</pre>
<pre>{{ objectCookieSecond.foo }}</pre>
<button @click="objectCookie.foo === 'baz' ? objectCookie.foo = 'bar' : objectCookie.foo = 'baz'">
<button @click="changeCookie">
Change cookie
</button>
<button @click="refreshCookie('browser-object-default')">