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
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.
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.