Skip to content

withModule

Composes a module component and its view into one component. Why the composition is shaped this way is on Props; this page is the API surface - the signature, the props of the component that comes back, and the one rule the view has to satisfy.

Signature

ts
withModule<M extends ComponentType<any>, V extends ComponentType<any>>(
    Module: M,
    View: V & ChildrenOnly<V>
): FC<ModuleProps<M> & ViewChildren<V>>

type ModuleProps<M> = Omit<ComponentProps<M>, "children">
type ViewChildren<V> = Pick<ComponentProps<V>, "children" & keyof ComponentProps<V>>
type ChildrenOnly<V> = keyof ComponentProps<V> extends "children"
    ? unknown
    : { "withModule: the view may declare no prop other than `children`": never }

Module is anything that renders a module boundary - a createModuleComponent result or a component wrapping ModuleProvider. View is what renders inside it. The three helper types are internal; they are written out here because they are what you read in an editor tooltip.

tsx
import { useResolve, withModule } from "@remodulo/react"

function OrdersView() {
    // The view declares no prop of its own. Everything it needs, it resolves.
    const store = useResolve(OrdersStore)
    return <ul>{store.orders.map((order) => <li key={order.id}>{order.title}</li>)}</ul>
}

// Props: the module's, minus `children`. displayName: `withModule(Module, OrdersView)`.
const Orders = withModule(OrdersModule, OrdersView)

The props that come back

The module's props, minus children, plus the view's children signature copied exactly. A view that requires children produces a composite that requires them; a view that declares none produces one that forbids them.

The view declares no prop other than children

The composition renders <View>{children}</View> and nothing else, so there is nowhere for another prop to come from. The type system refuses one up front, with the reason where the error text goes:

Argument of type '({ orderId }: { orderId: string; }) => ReactElement' is not assignable to parameter
of type '… & { "withModule: the view may declare no prop other than `children`": never; }'.

Everything the view needs, it resolves.

displayName

withModule(Module, OrdersView), taking each half's displayName, then its name, then Anonymous. A createModuleComponent result is called Module, so the common composite reads withModule(Module, OrdersView) in the React DevTools tree.

Where to go next

Guides

Reference

MIT licensed.