createInjectionState | VueUse

createInjectionState
​
Category
State
Export Size
132 B
Last Changed
2 months ago

Create global state that can be injected into components.

Demo
​

source

+
count: 0
double: 0
Usage
​
TypeScript
ts
// useCounterStore.ts
import { computed, ref } from 'vue'
import { createInjectionState } from '@vueuse/shared'
const [useProvideCounterStore, useCounterStore] = createInjectionState(
  (initialValue: number) => {
    // state
    const count = ref(initialValue)
    // getters
    const double = computed(() => count.value * 2)
    // actions
    function increment() {
      count.value++
    }
    return { count, double, increment }
  },
)
export { useProvideCounterStore }
// If you want to hide `useCounterStore` and wrap it in default value logic or throw error logic, please don't export `useCounterStore`
export { useCounterStore }
export function useCounterStoreWithDefaultValue() {
  return (
    useCounterStore() ?? {
      count: ref(0),
      double: ref(0),
      increment: () => {},
    }
  )
}
export function useCounterStoreOrThrow() {
  const counterStore = useCounterStore()
  if (counterStore == null)
    throw new Error(
      'Please call `useProvideCounterStore` on the appropriate parent component',
    )
  return counterStore
}
vue
<!-- RootComponent.vue -->
<script setup lang="ts">
import { useProvideCounterStore } from './useCounterStore'

useProvideCounterStore(0)
</script>

<template>
  <div>
    <slot />
  </div>
</template>
vue
<!-- CountComponent.vue -->
<script setup lang="ts">
import { useCounterStore } from './useCounterStore'

// use non-null assertion operator to ignore the case that store is not provided.
const { count, double } = useCounterStore()!
// if you want to allow component to working without providing store, you can use follow code instead:
// const { count, double } = useCounterStore() ?? { count: ref(0), double: ref(0) }
// also, you can use another hook to provide default value
// const { count, double } = useCounterStoreWithDefaultValue()
// or throw error
// const { count, double } = useCounterStoreOrThrow()
</script>

<template>
  <ul>
    <li>
      count: {{ count }}
    </li>
    <li>
      double: {{ double }}
    </li>
  </ul>
</template>
vue
<!-- ButtonComponent.vue -->
<script setup lang="ts">
import { useCounterStore } from './useCounterStore'

// use non-null assertion operator to ignore the case that store is not provided.
const { increment } = useCounterStore()!
</script>

<template>
  <button @click="increment">
    +
  </button>
</template>
Provide a custom InjectionKey
​
TypeScript
ts
// useCounterStore.ts
import { computed, ref } from 'vue'
import { createInjectionState } from '@vueuse/shared'
// custom injectionKey
const CounterStoreKey = 'counter-store'
const [useProvideCounterStore, useCounterStore] = createInjectionState(
  (initialValue: number) => {
    // state
    const count = ref(initialValue)
    // getters
    const double = computed(() => count.value * 2)
    // actions
    function increment() {
      count.value++
    }
    return { count, double, increment }
  },
  { injectionKey: CounterStoreKey },
)
Source
​

Source • Demo • Docs

Contributors
​
ZHAO Jin-Xiang
Anthony Fu
Peter Petau
丶远方
Tanimodori
Changelog
​
v10.5.0 on 10/7/2023
90d34 - feat: add injectionKey option (#3404)
5d948 - feat: allow provide and inject in same component (#3387)
v9.11.0 on 1/17/2023
f7ce6 - feat: return state when providing injection state (#2309)