createProvider
Collapses React Context + Provider component + useContext hook into a single call. Eliminates boilerplate when sharing hook state via React Context.
Basic — wrap a hook
Section titled “Basic — wrap a hook”import { import createProvider
createProvider, import useObservable
useObservable } from "@usels/web";
function function useCounterSetup(props: { initial: number;}): { count$: any; inc: () => any;}
useCounterSetup(props: { initial: number;}
props: { initial: number
initial: number }) { const const count$: any
count$ = import useObservable
useObservable(props: { initial: number;}
props.initial: number
initial); return { count$: any
count$, inc: () => any
inc: () => const count$: any
count$.any
set((v: any
v) => v: any
v + 1) };}
const [const CounterProvider: any
CounterProvider, const useCounter: any
useCounter] = import createProvider
createProvider(function useCounterSetup(props: { initial: number;}): { count$: any; inc: () => any;}
useCounterSetup);
// In your appfunction function App(): JSX.Element
App() { return ( <const CounterProvider: any
CounterProvider initial: number
initial={0}> <function Child(): JSX.Element
Child /> </const CounterProvider: any
CounterProvider> );}
function function Child(): JSX.Element
Child() { const { const count$: any
count$, const inc: any
inc } = const useCounter: any
useCounter(); return <JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button DOMAttributes<HTMLButtonElement>.onClick?: MouseEventHandler<HTMLButtonElement> | undefined
onClick={const inc: any
inc}>{const count$: any
count$.any
get()}</JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button>;}Non-strict mode — optional Provider
Section titled “Non-strict mode — optional Provider”By default, calling useContext outside a Provider throws.
Set strict: false to return undefined instead.
// @noErrorsimport { createProvider } from "@usels/web";
const [OptionalProvider, useMaybeValue] = createProvider( (props: { value: string }) => props.value, { strict: false });
function Child() { const ctx = useMaybeValue(); // string | undefined — no throw}Custom displayName
Section titled “Custom displayName”// @noErrorsimport { createProvider, useObservable } from "@usels/web";
const [ThemeProvider, useTheme] = createProvider( (props: { mode: "light" | "dark" }) => { const theme$ = useObservable(props.mode); return { theme$, toggle: () => theme$.set((v) => (v === "light" ? "dark" : "light")) }; }, { name: "Theme" });getHook — call from inside useScope / "use scope"
Section titled “getHook — call from inside useScope / "use scope"”The third tuple entry getHook is a non-hook accessor for the provided value.
Use it inside a useScope factory (or a "use scope" directive body) where
regular React hooks are disallowed.
// @noErrorsimport { computed, createProvider, observable } from "@usels/web";
const [ThemeProvider, useTheme, getTheme] = createProvider(({ color }: { color: string }) => observable({ color }));
function useThemeClass() { "use scope"; const theme$ = getTheme(); return { className$: computed(() => `theme-${theme$.color.get()}`) };}Rules:
- Must be called synchronously during the first run of the factory.
- Must be called under the matching Provider; otherwise throws in strict mode
or returns
undefinedin non-strict mode. - Returns the raw provided value (same as
useHook). For reactivity, provide an Observable from the composable — its reference stays stable andobserve()inside the scope reacts to field changes.