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
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 thePropsRef.token?: InjectionToken<PropsRef<T>>- what the bridge registers under. Defaults to thePropsRefclass 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.
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.