Skip to content
← Todas las preguntas
Intermedio

¿Qué es Provide/Inject?

ComponentesComposition API

Cuando un componente padre necesita pasar datos a un hijo profundamente anidado, normalmente tendrías que pasar props a través de cada componente intermedio, aunque esos componentes no usen los datos. Esto se llama "prop drilling", y hace el código frágil y difícil de mantener.

provide e inject resuelven esto. Un padre provee datos, y cualquier descendiente —sin importar la profundidad— puede inyectarlos directamente sin que ningún componente intermedio sepa de ellos.

Cómo funciona

vue
<!-- GrandParent.vue -->
<script setup lang="ts">
import { provide, ref } from 'vue'

const theme = ref('dark')
provide('theme', theme)
</script>
vue
<!-- DeeplyNestedChild.vue (cualquier nivel por debajo de GrandParent) -->
<script setup lang="ts">
import { inject } from 'vue'

const theme = inject('theme') // 'dark' — sin props pasadas por componentes intermedios
</script>

El valor provisto es reactivo. Cuando theme cambia en el padre, cada componente que lo inyectó se actualiza automáticamente.

Inyección tipada con InjectionKey

Las claves de string funcionan pero no ofrecen seguridad de tipos. Usa InjectionKey para provide/inject tipados:

ts
// keys.ts
import type { InjectionKey, Ref } from 'vue'

interface User { name: string; role: string }

export const UserKey: InjectionKey<Ref<User>> = Symbol('user')
ts
// Provider
import { provide, ref } from 'vue'
import { UserKey } from '@/keys'

const user = ref<User>({ name: 'John', role: 'admin' })
provide(UserKey, user)
ts
// Consumer
import { inject } from 'vue'
import { UserKey } from '@/keys'

const user = inject(UserKey) // Ref<User> | undefined
const user = inject(UserKey, ref({ name: 'Guest', role: 'viewer' })) // con valor por defecto

Cuándo usarlo (y cuándo no)

Buenos casos de uso:

  • Tema o configuración regional compartida en toda la app
  • Estado de autenticación/usuario accesible en lo profundo del árbol
  • Contexto de tabla o formulario (un <Table> provee configuración de columnas, el <TableCell> hijo lo inyecta)
  • Funcionalidades tipo plugin (un gestor de toasts, un gestor de modales)

Malos casos de uso:

  • Pasar datos entre componentes hermanos — provide/inject es solo de ancestro a descendiente
  • Reemplazar todas las props con inject — hace los componentes más difíciles de testear y entender porque sus dependencias son implícitas
  • Estado global que muchos componentes no relacionados leen y escriben — usa Pinia en su lugar

Provide/Inject vs Props vs Pinia

PropsProvide/InjectPinia
DirecciónPadre → hijo (1 nivel)Ancestro → cualquier descendienteCualquier componente → cualquier componente
ExplícitoSí (visible en la plantilla)No (dependencia implícita)Parcialmente (importar store)
Reactivo
Mejor paraDatos padre-hijo directosContexto de un subárbolEstado global de la app

Ver también: ¿Qué es getCurrentInstance() y por qué deberías evitarlo? · ¿Qué es un composable?

Referencias

Publicado bajo la licencia MIT.