Skip to content

createModuleComponent

The factory that turns a module boundary and a props bridge into one component. The semantics behind the two prop channels are on Props; this page is the API surface - the signature, the two argument shapes, and what the returned component renders.

Signature

ts
createModuleComponent<P extends object = {}, T extends object = P>(
    config?: ModuleConfig | ((props: T) => ModuleConfig),
    props?: PropsBridgeOptions<P, T>
): ComponentType<P & { children?: ReactNode }>

P is what the parent writes in JSX. T is what services see - the same thing unless use enriches it. Both infer from the arguments when you pass a config function.

config

ModuleConfig is ModuleProvider's props without children: id, providers, deps, and the four module hooks onModuleInit, onModuleMount, onModuleUnmount, onModuleDestroy.

Pass an object for a module that does not depend on props. Pass a function of the enriched props for one that does - it runs on every render, and its result is honoured when the module is created and when it is rebuilt. It is not a hook and must not call one.

props

PropsBridgeOptions has three keys, all optional:

  • use?: (props: P) => T - a custom hook that enriches the raw props. It runs unconditionally on every render and may call any other hook. Pass a named function declared once; its identity is captured here.
  • adapter?: PropsAdapter<T> - a pure update-time transform applied inside the PropsRef.
  • token?: InjectionToken<PropsRef<T>> - what the bridge registers under. Defaults to the PropsRef class itself.

deps

deps?: unknown[] sits in ModuleConfig and follows React's hook-deps rule exactly: element-wise Object.is plus a length comparison, and undefined on either side never triggers. Anything that changes destroys the module and builds a new one, with new instances throughout. The rebuild runs on a layout effect, so several render attempts with the same new dependency build one module.

tsx
import { createModuleComponent } from "@remodulo/react"

const OrdersModule = createModuleComponent<OrderProps, OrderContext>(
    // Birth configuration: evaluated every render, honoured at create and at rebuild.
    (props) => ({
        id: `orders:${props.orderId}`,
        providers: [OrdersStore],
        deps: [props.workspaceId],
    }),
    // The bridge: `use` sources the enriched props, `token` names the ref services inject.
    { use: useOrderContext, token: OrderPropsRef }
)

What it renders

A ModuleProvider whose providers array is the bridge's provider followed by yours, wrapping children. The component's displayName is Module.

Where to go next

Guides

Reference

MIT licensed.