We use cookies to enhance your experience on the site
CodeWorlds

Provide / Inject

When NOVA LAB broadcasts a message to the entire colony, it doesn't send it through each module individually - it uses a broadcast system. In Vue, this mechanism is provide/inject - passing data through multiple levels without prop drilling.

The Prop Drilling Problem

Without provide/inject you must pass props through every level:

1App → Layout → Page → Sidebar → DeepChild
2(theme)  (theme)  (theme)  (theme)  (theme) 😩

With provide/inject:

1App (provide theme) → ... → DeepChild (inject theme) 🎉

Provide/Inject Basics

1<!-- Provider (ancestor) -->
2<script setup>
3import { provide, ref } from 'vue'
4
5const theme = ref('dark')
6provide('theme', theme)
7provide('labName', 'NOVA LAB Alpha')
8</script>
9
10<!-- Consumer (any descendant) -->
11<script setup>
12import { inject } from 'vue'
13
14const theme = inject('theme')
15const labName = inject('labName')
16
17// With default value
18const mode = inject('mode', 'standard')
19</script>

Reactive Provide

Pass

ref()
or
reactive()
so data is reactive:

1<!-- Provider -->
2<script setup>
3import { provide, ref, readonly } from 'vue'
4
5const count = ref(0)
6
7// Readonly - descendant cannot modify
8provide('count', readonly(count))
9
10// Actions for modification
11provide('increment', () => count.value++)
12</script>
13
14<!-- Consumer -->
15<script setup>
16import { inject } from 'vue'
17
18const count = inject('count')       // readonly ref
19const increment = inject('increment') // function
20</script>

App-level Provide

Global provide in

main.ts
:

1const app = createApp(App)
2app.provide('apiUrl', 'https://mars-api.novalab.space')
3app.mount('#app')

Typed Keys (InjectionKey)

1import type { InjectionKey, Ref } from 'vue'
2
3export const themeKey: InjectionKey<Ref<string>> = Symbol('theme')
4
5// Provider
6provide(themeKey, ref('dark'))
7
8// Consumer - TypeScript knows it's Ref<string>
9const theme = inject(themeKey)
Go to CodeWorlds