--- title: Provide Must Be Called Synchronously During Setup impact: HIGH impactDescription: Calling provide() asynchronously or conditionally may fail silently or cause inconsistent injection behavior type: gotcha tags: [vue3, provide-inject, composition-api, async, setup] --- # Provide Must Be Called Synchronously During Setup **Impact: HIGH** - The `provide()` function must be called synchronously during the component's `setup()` phase. Calling it asynchronously (inside callbacks, promises, or after await) will fail silently, and descendant components will not receive the provided value. ## Task Checklist - [ ] Always call `provide()` at the top level of `setup()` or ` ``` **Wrong - Provide inside callback:** ```vue ``` **Wrong - Provide after await in setup:** ```vue ``` ## Solution: Provide Synchronously, Update Async **Correct - Provide ref immediately, update later:** ```vue ``` ```vue ``` ## Pattern: Async Data Provider Create a reusable pattern for async-provided data: ```vue ``` Usage: ```vue ``` ## Why This Happens Vue's `provide()` relies on the current component instance context, which is only available synchronously during setup. After setup completes: 1. The setup context is cleared 2. `provide()` can't find the current instance 3. The call fails silently (no error thrown) ## Checking for Setup Context You can verify if setup context is available: ```js import { getCurrentInstance } from 'vue' function debugProvide(key, value) { const instance = getCurrentInstance() if (!instance) { console.error( `provide() called outside setup context. ` + `Key: ${String(key)}. This will fail silently.` ) return } provide(key, value) } ``` ## App-Level Provide (Exception) `app.provide()` can be called anytime during app initialization: ```js // main.js import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) // This works - app-level provide app.provide('appConfig', { version: '1.0.0' }) // Even async is OK at app level before mount fetchConfig().then(config => { app.provide('apiConfig', config) app.mount('#app') }) ``` But once the app is mounted, `app.provide()` should not be called. ## Reference - [Vue.js Composition API - provide()](https://vuejs.org/api/composition-api-dependency-injection.html#provide) - [Vue.js Provide/Inject Guide](https://vuejs.org/guide/components/provide-inject.html)