Skip to content
Meeko
Type to search the guides and the API reference. Open it from any page with / or Ctrl K; move with the arrow keys and open a result with Enter.
Get started

Contents

On this page

inject

Reads the value provided with provide by the nearest ancestor and fails if none provided it.

reactivity Since 1.0.0 No import @meekojs/meeko Source code

Se autoimporta en las aplicaciones del framework.

ts
import { inject } from "@meekojs/meeko";

inject(key) walks up the active component's roots (the component itself, its parent, its parent's parent…) and returns the value from the first one that provided key with provide. If none did, it throws an error with the key's description instead of returning undefined: a missing context is a structural failure, not a case the template should handle.

It is exported from @meekojs/meeko and auto-imported in framework applications.

Usage#

meeko
<!-- app/components/ThemeBadge.meeko -->
<script lang="ts">
import { themeKey } from "../composables/theme";
const theme = inject(themeKey); // Signal<"light" | "dark">
</script>

<template><span class="badge" bind:data-theme="theme.value">Theme {theme.value}</span></template>

Because the layout provided a signal, the badge updates when the theme changes.

Type#

ts
function inject<T>(key: ContextKey<T>): T

ContextKey

ts
type ContextKey<T> = symbol & {
	readonly __meekoValue?: (value: T) => T
}

Parameters#

Parameter Type Default Description
key ContextKey<T> required Key created with createContext. The same instance used by provide, not another with the same description.

Return value#

The value T from the nearest provider. If no ancestor provided the key, it throws Error: Missing Meeko context: <descripción> (without a description, Missing Meeko context).

Examples#

A composable that wraps inject#

Export a named function instead of the key: its users do not need to know there is a context.

ts
// app/composables/session.ts
import { createContext, inject } from "@meekojs/meeko";
import type { ReadonlySignal } from "@meekojs/meeko";

export const sessionKey = createContext<ReadonlySignal<{ name: string } | null>>("session");
export const useSessionUser = (): ReadonlySignal<{ name: string } | null> => inject(sessionKey);
meeko
<script lang="ts">
const user = useSessionUser();
</script>

<template><p if:when="user.value">Hello, {user.value.name}</p></template>

The nearest provider wins#

ts
import { createContext, createRoot, inject, provide } from "@meekojs/meeko";

const sizeKey = createContext<"sm" | "md">("size");
const size = createRoot(() => {
  provide(sizeKey, "md");
  return createRoot(() => {
    provide(sizeKey, "sm");
    return createRoot(() => inject(sizeKey));
  });
});
// size === "sm"

An optional context#

inject has no default value. If a component must work with and without a provider, provide the default value in app/app.meeko or handle the case with try:

ts
import { inject } from "@meekojs/meeko";
import type { ContextKey } from "@meekojs/meeko";

export function injectOr<T>(key: ContextKey<T>, fallback: T): T {
  try { return inject(key); }
  catch { return fallback; }
}

Common mistakes#

A component outside the provider#

Incorrectmeeko
<!-- app/pages/index.meeko: the layout does not call provide(themeKey, …) -->
<ThemeBadge />

Rendering fails with Error: Missing Meeko context: theme. Provide the value in an ancestor of all its readers, such as the layout or app/app.meeko:

Correctmeeko
<!-- app/layouts/default.meeko -->
<script lang="ts">
import { themeKey } from "../composables/theme";
provide(themeKey, signal<"light" | "dark">("light"));
</script>

Calling it in a handler or after an await#

inject searches from the active root, which only exists while the component script runs.

Incorrectts
async function save(): Promise<void> {
  await persist();
  inject(toastsKey).show("Saved");
}

Outside the script there is no active root, and it throws Missing Meeko context: toasts. Call inject at the top level of the script and keep the value:

Correctts
const toasts = inject(toastsKey);
async function save(): Promise<void> {
  await persist();
  toasts.show("Saved");
}

Reading the value instead of the signal#

Incorrectts
const theme = inject(themeKey).value;

theme is the text at that moment: the template does not update when the theme changes. Keep the signal and read .value where you use it:

Correctts
const theme = inject(themeKey);
// <span>{theme.value}</span>

Notes#

  • Server and browser. It works the same in both, with values provided by ancestors in that same execution.
  • Where to call it. At the top level of the script or in a composable it calls. The content of a snippet or a <MeekoTeleport> sees the contexts of the component that declares it.
  • Siblings. Only ancestors are searched: a sibling that provided the key does not count.
  • Meeko context. useState, useRoute, useNavigation and other framework composables rely on this same mechanism. That is why useState outside an application throws Missing Meeko context: Meeko framework state.

Was this page helpful?

Add a comment

It is sent when you choose “Yes” or “No”. Only the page, your answer and the comment are stored: no cookies and no personal data.

0 of 2000 characters

Edit on GitHub: docs/en/reference/reactivity/inject.md