Ahead of the release
npm install @evanion/react-widget gives you 0.3.0. These pages document main, which has changes that release does not.
@evanion/react-widget
Render a region of React components from structured data — a shop page, a back-office view, a configurable shelf — with the data checked against the components at compile time. Baize’s shelf below is two widget types and the items the shop’s data gives them.
import { } from '@evanion/react-widget';
const = ({ , }: { : string; : number }) => (
< ="listing">
<>{}</>
<>{} kr</>
</>
);
const = ({
,
,
}: {
: number;
: boolean;
}) => (
< ="booking">
<>{} tables</>
<>{ ? 'tonight' : 'this week'}</>
</>
);
// Call once, at module scope.
const { , } = ({
: { : , : },
: {
: ({ }) => < ="shelf">{}</>,
},
});
export function () {
return (
<
={[
{ : 'b1', : 'booking', : { : 4, : true } },
{
: 'g1',
: 'listing',
: { : 'Brass: Birmingham', : 649 },
},
]}
/>
);
}The component map drives everything. An unknown type, a missing or mistyped
prop, or children on a component that does not accept them is a compile error
rather than a warning in a console somebody has to be watching.
Server components
The package carries no 'use client'. It uses only what React exports under the
react-server condition — createElement, Suspense, memo — and no
createContext, useContext, Component or stateful hook. A page that renders
<Widgets> can be a Server Component, and a widget can be an async Server
Component that fetches its own data.
There is no provider, no hook and no class error boundary here, because
react/package.json maps the react-server condition to a build that does not
export the APIs those need. What would have been context is a prop: ctx for
page-level data, meta for placement.
What it gives you
| Piece | What it does |
|---|---|
createWidgets | builds a widget set from a component map; call once at module scope |
Widgets | renders a list of items |
defineItems | supplies the contextual type for an item array held in a variable |
validateItems | checks data that never met the type checker, at ingestion or in CI |
chrome | wrapper, per-item wrapper, Suspense boundary and fallback |
meta | placement data that reaches the item chrome and never the widget |
ctx | page-level data passed to every widget as a prop |
Where to go next
- Getting started — install, the component map, typing items
- API reference — every export, every prop, every type
- Chrome,
metaand Suspense — the composition seams - Examples — worked regions
- Playground — run it in the browser
- Migrating from 0.1.x — the RSC redesign
Related packages
@evanion/astro-widget is the same idea for Astro: a registry instead of a
component map, ctx instead of a provider, and no recursion into children
because an Astro component receives child content through <slot />.
@evanion/compose handles the neighbouring problem of nesting providers, for
the parts of an app that do have context.