Skip to content
Primitives

inject

Reads a React Context value from inside a useScope factory (or a "use scope" directive body) where regular React hooks cannot be called. The scope records the Context during the first mount and replays React.useContext(ctx) in the same order on every subsequent render, so the component correctly subscribes to Context updates without violating the rules of hooks.

import
(alias) namespace React
import React
React
from "react";
import {
import inject
inject
,
import createObserve
createObserve
,
import useScope
useScope
} from "@usels/web";
const
const ThemeCtx: React.Context<"light" | "dark">
ThemeCtx
=
(alias) namespace React
import React
React
.
function createContext<"light" | "dark">(defaultValue: "light" | "dark"): React.Context<"light" | "dark">

Lets you create a

Context

that components can provide or read.

@paramdefaultValue The value you want the context to have when there is no matching Provider in the tree above the component reading the context. This is meant as a "last resort" fallback.

@seehttps://react.dev/reference/react/createContext#reference React Docs

@seehttps://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/context/ React TypeScript Cheatsheet

@example

import { createContext } from 'react';
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext value="dark">
<Toolbar />
</ThemeContext>
);
}

createContext
<"light" | "dark">("light");
function
function useThemeClass(): any
useThemeClass
() {
return
import useScope
useScope
(() => {
const
const theme: any
theme
=
import inject
inject
(
const ThemeCtx: React.Context<"light" | "dark">
ThemeCtx
); // reads from nearest ThemeCtx.Provider
import createObserve
createObserve
(() => {
any
document
.
any
documentElement
.
any
dataset
.
any
theme
=
const theme: any
theme
;
});
return {};
});
}

Reactive Context — provide an Observable

Section titled “Reactive Context — provide an Observable”

inject returns the raw Context value. When the Provider supplies an Observable, its reference is stable and createObserve() inside the scope reacts to field changes — the idiomatic pattern used by createProvider.

import React from "react";
import { observable } from "@legendapp/state";
import { inject, createObserve, useScope } from "@usels/web";
const counter$ = observable({ n: 1 });
const CounterCtx = React.createContext(counter$);
function useCounterLog() {
return useScope(() => {
const c$ = inject(CounterCtx); // stable reference
createObserve(() => {
console.log("count:", c$.n.get()); // reacts to field changes
});
return {};
});
}

Each inject() call is recorded in order on the first mount and replayed in the same order on every re-render. Call inject() unconditionally at the top of the factory — the same rule as regular React hooks.

import React from "react";
import { inject, useScope } from "@usels/web";
const A = React.createContext(1);
const B = React.createContext("b");
const C = React.createContext(true);
function useAbc() {
return useScope(() => {
const a = inject(A);
const b = inject(B);
const c = inject(C);
return { a, b, c };
});
}
  • Call synchronously during the first run of the factory. inject() records the Context on mount and replays it on re-render. Calls from setTimeout, Promise.then, onMount, onUnmount, event handlers, or any other deferred callback throw because the recorder is already torn down.
  • Do not call conditionally. The set of inject() calls must be stable across renders — the first mount defines the replay order. Conditional branches that add or skip an inject() break the replay order.
  • Reactivity flows through references. inject() returns the raw Context value. A Provider that swaps the value identity triggers a component re-render (standard React Context behavior). For fine-grained reactivity without re-rendering, provide an Observable and read fields via createObserve() / .get().
  • Strict Mode safe. Even when React double-invokes the factory in development Strict Mode, the Context is recorded exactly once.
inject() must be called inside useScope factory (during first mount)

Thrown when inject() is called outside an active scope recorder — typically from an async callback, a lifecycle hook (onMount/onUnmount), or a standalone function not wrapped by useScope.

createProvider returns a tuple [Provider, useHook, getHook]. The third entry getHook is implemented with inject() — use it to read the provided value inside a useScope factory without calling React hooks.

View on GitHub