mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
feat(nuxt): tryUseNuxtApp
composable (#25031)
This commit is contained in:
parent
2bfe01d26f
commit
6b651cf7bf
@ -28,6 +28,8 @@ You can think of it as **Runtime Core**.
|
|||||||
This context can be accessed using [`useNuxtApp()`](/docs/api/composables/use-nuxt-app) composable within Nuxt plugins and `<script setup>` and vue composables.
|
This context can be accessed using [`useNuxtApp()`](/docs/api/composables/use-nuxt-app) composable within Nuxt plugins and `<script setup>` and vue composables.
|
||||||
Global usage is possible for the browser but not on the server, to avoid sharing context between users.
|
Global usage is possible for the browser but not on the server, to avoid sharing context between users.
|
||||||
|
|
||||||
|
Since [`useNuxtApp`](/docs/api/composables/use-nuxt-app) throws an exception if context is currently unavailable, if your composable does not always require `nuxtApp`, you can use [`tryUseNuxtApp`](/docs/api/composables/use-nuxt-app#tryusenuxtapp) instead, which will return `null` instead of throwing an exception.
|
||||||
|
|
||||||
To extend the `nuxtApp` interface and hook into different stages or access contexts, we can use [Nuxt Plugins](/docs/guide/directory-structure/plugins).
|
To extend the `nuxtApp` interface and hook into different stages or access contexts, we can use [Nuxt Plugins](/docs/guide/directory-structure/plugins).
|
||||||
|
|
||||||
Check [Nuxt App](/docs/api/composables/use-nuxt-app) for more information about this interface.
|
Check [Nuxt App](/docs/api/composables/use-nuxt-app) for more information about this interface.
|
||||||
|
@ -30,6 +30,8 @@ export function useMyComposable () {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If your composable does not always need `nuxtApp` or you simply want to check if it is present or not, since [`useNuxtApp`](/docs/api/composables/use-nuxt-app) throws an exception, you can use [`tryUseNuxtApp`](/docs/api/composables/use-nuxt-app#tryusenuxtapp) instead.
|
||||||
|
|
||||||
Plugins also receive `nuxtApp` as the first argument for convenience.
|
Plugins also receive `nuxtApp` as the first argument for convenience.
|
||||||
|
|
||||||
:read-more{to="/docs/guide/directory-structure/plugins"}
|
:read-more{to="/docs/guide/directory-structure/plugins"}
|
||||||
|
@ -16,6 +16,8 @@ const nuxtApp = useNuxtApp()
|
|||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If runtime context is unavailable in your scope, `useNuxtApp` will throw an exception when called. You can use [`tryUseNuxtApp`](#tryusenuxtapp) instead for composables that do not require `nuxtApp`, or to simply check if context is available or not without an exception.
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
### `provide (name, value)`
|
### `provide (name, value)`
|
||||||
@ -257,3 +259,22 @@ Native async context support works currently in Bun and Node.
|
|||||||
::
|
::
|
||||||
|
|
||||||
:read-more{to="/docs/guide/going-further/experimental-features#asynccontext"}
|
:read-more{to="/docs/guide/going-further/experimental-features#asynccontext"}
|
||||||
|
|
||||||
|
## tryUseNuxtApp
|
||||||
|
|
||||||
|
This function works exactly the same as `useNuxtApp`, but returns `null` if context is unavailable instead of throwing an exception.
|
||||||
|
|
||||||
|
You can use it for composables that do not require `nuxtApp`, or to simply check if context is available or not without an exception.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
```ts [composable.ts]
|
||||||
|
export function useStandType() {
|
||||||
|
// Always works on the client
|
||||||
|
if (tryUseNuxtApp()) {
|
||||||
|
return useRuntimeConfig().public.STAND_TYPE
|
||||||
|
} else {
|
||||||
|
return process.env.STAND_TYPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -439,8 +439,10 @@ export function callWithNuxt<T extends (...args: any[]) => any> (nuxt: NuxtApp |
|
|||||||
/*@__NO_SIDE_EFFECTS__*/
|
/*@__NO_SIDE_EFFECTS__*/
|
||||||
/**
|
/**
|
||||||
* Returns the current Nuxt instance.
|
* Returns the current Nuxt instance.
|
||||||
|
*
|
||||||
|
* Returns `null` if Nuxt instance is unavailable.
|
||||||
*/
|
*/
|
||||||
export function useNuxtApp (): NuxtApp {
|
export function tryUseNuxtApp (): NuxtApp | null {
|
||||||
let nuxtAppInstance
|
let nuxtAppInstance
|
||||||
if (hasInjectionContext()) {
|
if (hasInjectionContext()) {
|
||||||
nuxtAppInstance = getCurrentInstance()?.appContext.app.$nuxt
|
nuxtAppInstance = getCurrentInstance()?.appContext.app.$nuxt
|
||||||
@ -448,6 +450,18 @@ export function useNuxtApp (): NuxtApp {
|
|||||||
|
|
||||||
nuxtAppInstance = nuxtAppInstance || nuxtAppCtx.tryUse()
|
nuxtAppInstance = nuxtAppInstance || nuxtAppCtx.tryUse()
|
||||||
|
|
||||||
|
return nuxtAppInstance || null
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@__NO_SIDE_EFFECTS__*/
|
||||||
|
/**
|
||||||
|
* Returns the current Nuxt instance.
|
||||||
|
*
|
||||||
|
* Throws an error if Nuxt instance is unavailable.
|
||||||
|
*/
|
||||||
|
export function useNuxtApp (): NuxtApp {
|
||||||
|
const nuxtAppInstance = tryUseNuxtApp()
|
||||||
|
|
||||||
if (!nuxtAppInstance) {
|
if (!nuxtAppInstance) {
|
||||||
if (import.meta.dev) {
|
if (import.meta.dev) {
|
||||||
throw new Error('[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables`.')
|
throw new Error('[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables`.')
|
||||||
|
@ -18,7 +18,7 @@ const granularAppPresets: InlinePreset[] = [
|
|||||||
imports: ['defineNuxtLink']
|
imports: ['defineNuxtLink']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
imports: ['useNuxtApp', 'defineNuxtPlugin', 'definePayloadPlugin', 'useRuntimeConfig', 'defineAppConfig'],
|
imports: ['useNuxtApp', 'tryUseNuxtApp', 'defineNuxtPlugin', 'definePayloadPlugin', 'useRuntimeConfig', 'defineAppConfig'],
|
||||||
from: '#app/nuxt'
|
from: '#app/nuxt'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2130,6 +2130,12 @@ describe.skipIf(process.env.TEST_CONTEXT !== 'async')('Async context', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe.skipIf(process.env.TEST_CONTEXT === 'async')('Async context', () => {
|
||||||
|
it('should be unavailable', async () => {
|
||||||
|
expect(await $fetch('/async-context')).toContain('"hasApp": false')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe.skipIf(isWindows)('useAsyncData', () => {
|
describe.skipIf(isWindows)('useAsyncData', () => {
|
||||||
it('works after useNuxtData call', async () => {
|
it('works after useNuxtData call', async () => {
|
||||||
const page = await createPage('/useAsyncData/nuxt-data')
|
const page = await createPage('/useAsyncData/nuxt-data')
|
||||||
|
@ -12,7 +12,7 @@ async function fn1 () {
|
|||||||
|
|
||||||
async function fn2 () {
|
async function fn2 () {
|
||||||
await delay()
|
await delay()
|
||||||
const app = useNuxtApp()
|
const app = tryUseNuxtApp()
|
||||||
return {
|
return {
|
||||||
hasApp: !!app
|
hasApp: !!app
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user