feat(nuxt): provide clearNuxtState composable (#21409)

This commit is contained in:
Jongmin Yoon 2023-06-10 06:22:21 +09:00 committed by GitHub
parent 357ad9bd31
commit 31a1b98f3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 44 additions and 4 deletions

View File

@ -59,6 +59,10 @@ const counter = useState('counter', () => Math.round(Math.random() * 1000))
::ReadMore{link="/docs/api/composables/use-state"}
::
::alert{icon=📘}
To globally invalidate cached state, see [`clearNuxtState`](/docs/api/utils/clear-nuxt-state).
::
### Advanced Usage
In this example, we use a composable that detects the user's default locale from the HTTP request headers and keeps it in a `locale` state.

View File

@ -12,4 +12,4 @@ clearNuxtData (keys?: string | string[] | ((key: string) => boolean)): void
## Parameters
* `keys`: On or an array of keys that are used in `useAsyncData` to delete their cached data. If no keys are provided, **every data** will be invalidated.
* `keys`: One or an array of keys that are used in `useAsyncData` to delete their cached data. If no keys are provided, **all data** will be invalidated.

View File

@ -0,0 +1,15 @@
# `clearNuxtState`
Delete cached state of `useState`.
This method is useful if you want to invalidate the state of `useState`.
## Type
```ts
clearNuxtState (keys?: string | string[] | ((key: string) => boolean)): void
```
## Parameters
* `keys`: One or an array of keys that are used in `useState` to delete their cached state. If no keys are provided, **all state** will be invalidated.

View File

@ -16,7 +16,7 @@ export { defineNuxtComponent } from './component'
export { useAsyncData, useLazyAsyncData, useNuxtData, refreshNuxtData, clearNuxtData } from './asyncData'
export type { AsyncDataOptions, AsyncData } from './asyncData'
export { useHydration } from './hydrate'
export { useState } from './state'
export { useState, clearNuxtState } from './state'
export { clearError, createError, isNuxtError, showError, useError } from './error'
export type { NuxtError } from './error'
export { useFetch, useLazyFetch } from './fetch'

View File

@ -2,6 +2,7 @@ import { isRef, toRef } from 'vue'
import type { Ref } from 'vue'
import { useNuxtApp } from '../nuxt'
const useStateKeyPrefix = '$s'
/**
* Create a global reactive ref that will be hydrated but not shared across ssr requests
*
@ -20,7 +21,7 @@ export function useState <T> (...args: any): Ref<T> {
if (init !== undefined && typeof init !== 'function') {
throw new Error('[nuxt] [useState] init must be a function: ' + init)
}
const key = '$s' + _key
const key = useStateKeyPrefix + _key
const nuxt = useNuxtApp()
const state = toRef(nuxt.payload.state, key)
@ -35,3 +36,22 @@ export function useState <T> (...args: any): Ref<T> {
}
return state
}
export function clearNuxtState (
keys?: string | string[] | ((key: string) => boolean)
): void {
const nuxtApp = useNuxtApp()
const _allKeys = Object.keys(nuxtApp.payload.state)
const _keys: string[] = !keys
? _allKeys
: typeof keys === 'function'
? _allKeys.filter(keys)
: Array.isArray(keys) ? keys : [keys]
for (const _key of _keys) {
const key = useStateKeyPrefix + _key
if (key in nuxtApp.payload.state) {
nuxtApp.payload.state[key] = undefined
}
}
}

View File

@ -27,6 +27,7 @@ const appPreset = defineUnimportPreset({
'reloadNuxtApp',
'useRuntimeConfig',
'useState',
'clearNuxtState',
'useFetch',
'useLazyFetch',
'useCookie',

View File

@ -36,7 +36,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
it('default server bundle size', async () => {
stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"62.8k"')
expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"62.9k"')
const modules = await analyzeSizes('node_modules/**/*', serverDir)
expect(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"2286k"')