Skip to Content
React WidgetGetting Started

Getting started

@evanion/react-widget 0.3.0 and its patch releases up to 0.3.3, the version on npm. Values on this page were produced by running the source at f9b1d93, a later commit than the 0.3.0 tag, and are not re-executed.

In this guide, you will build a component-driven page using @evanion/react-widget. You’ll learn how to map CMS-style data to React components and how to ensure that your items are type-safe, preventing runtime crashes when a component receives the wrong data.

Prerequisites

To follow this guide, ensure you have the following:

  • Node 20 or newer.
  • React 18 or 19: Along with react-dom at the same version.
  • An ES module project: Your package.json must include "type": "module".
  • TypeScript 5.0 or newer: Ensure your tsconfig.json has "jsx": "react-jsx" under compilerOptions to allow JSX without importing React.

To set up a fresh project for this example, run:

npm init -y npm pkg set type=module npm install --save-dev typescript tsx @types/react @types/react-dom npx tsc --init --jsx react-jsx

Install react-widget

Run the command for your preferred package manager (this will also install React and react-dom):

npm install @evanion/react-widget react react-dom

Render your first widget region

The primary entry point is createWidgets. It takes a component map (linking widget types to React components) and returns a Widgets component and a defineItems helper.

The “Type-Safe Array” Problem

Because TypeScript normally widens string types in arrays, passing a variable to <Widgets> would normally result in a compile error. defineItems solves this by typing the array against your component map, ensuring every type is a valid key and every props object matches the component’s requirements.

Here is how to render a Baize listing to HTML using renderToStaticMarkup:

const = (: { : string; : number }) => ( <> {.}, {.} kr </> ); // 1. Create a typed widget set from the component map const { , } = ({ : { : }, }); // 2. Define items with compile-time prop checking const = ([ { : 'brass', : 'listing', : { : 'Brass: Birmingham', : 649 }, }, ]); // 3. Render the region const = (< ={} />); // -> '<section><div data-widget-id="brass" data-widget-type="listing"><h3>Brass: Birmingham, 649 kr</h3></div></section>'

How to run the example:

  1. Create render.tsx and import createWidgets and renderToStaticMarkup.
  2. Paste the code above and add console.log(html); at the end.
  3. Run npx tsx render.tsx.

The output will show a <section> (the default chrome.wrapper) containing a <div> (the default chrome.item) which wraps the actual ListingCard markup.

Verifying Type Safety

While tsx runs the code immediately, you can verify the type safety by running npx tsc --noEmit. If you change a price from a number to a string in your items, TypeScript will report a type mismatch, preventing a potential runtime error in your component.

Important: Call createWidgets once at the module scope. Calling it inside a component will cause the entire region to remount on every render, destroying the internal state of your widgets.

Expanding your layout

You now have a single region rendering a list of items. In a real application, you often need to group these items—for example, putting a set of listings inside a “Featured” showcase.

In Nesting items, we’ll explore how to create widgets that can contain other widgets.

Last updated on