Skip to content
Utilities

createProvider

Collapses React Context + Provider component + useContext hook into a single call. Eliminates boilerplate when sharing hook state via React Context.

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 app
function
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
>;
}

By default, calling useContext outside a Provider throws. Set strict: false to return undefined instead.

// @noErrors
import { createProvider } from "@usels/web";
const [OptionalProvider, useMaybeValue] = createProvider(
(props: { value: string }) => props.value,
{ strict: false }
);
function Child() {
const ctx = useMaybeValue(); // string | undefined — no throw
}
// @noErrors
import { 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.

// @noErrors
import { 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 undefined in non-strict mode.
  • Returns the raw provided value (same as useHook). For reactivity, provide an Observable from the composable — its reference stays stable and observe() inside the scope reacts to field changes.

View on GitHub