rudra-js

extendRegistry

import { extendRegistry } from '@rudra-js/react';

Call extendRegistry to swap in your own component for one kind of block and keep the built-in renderers for the rest.

extendRegistry(overrides: Partial<BlockRegistry>) => BlockRegistry

Reference

extendRegistry(overrides)

Parameters

  • overrides: Your renderers, keyed by block kind, such as grid. Each one is a component that gets two props:
    • block: The block to draw. The fields of each kind are under Fields.
    • context: What the block needs from the RudraComponent it sits in:
      • products: Your products, keyed by SKU. Call get(sku) to read one.
      • bundles: Your bundles, keyed by set id.
      • hrefForSku: The hrefForSku prop, or the default.
      • formatPrice: The formatPrice prop, or the default with locale applied.
      • formatBundlePrice: The formatBundlePrice prop, or the default with locale applied.

Returns

A BlockRegistry with a renderer for every kind. Pass it to RudraComponent as registry.

Caveats

  • A kind you leave out, or pass as undefined, keeps the built-in renderer.
  • The model never sees your renderers. It writes the same blocks either way.
  • A dropped block never reaches your renderer. RudraComponent says which blocks it drops.
  • context.products.get(sku) can return undefined, or a product with isInStock: false. Skip both, as the built-in renderers do.
  • Render the model's words as text. Never pass them to dangerouslySetInnerHTML.

Fields

NameTypeDefaultConstraints
kind"hero"
headlinestring
bodystringnullable
skustringnullable
ctaLabelstringnullable
NameTypeDefaultConstraints
kind"grid"
titlestringnullable
columns2 | 3 | 4
itemsProductReference[]
items.skustring
items.basis"similar_to_current" | "most_viewed" | "complements_cart" | "complements_purchase" | "liked_category" | "popular"
items.reasonstringnullable
items.badgestringnullable
items.emphasis"normal" | "featured"
NameTypeDefaultConstraints
kind"carousel"
titlestringnullable
itemsProductReference[]
items.skustring
items.basis"similar_to_current" | "most_viewed" | "complements_cart" | "complements_purchase" | "liked_category" | "popular"
items.reasonstringnullable
items.badgestringnullable
items.emphasis"normal" | "featured"
NameTypeDefaultConstraints
kind"banner"
tone"info" | "promo" | "urgency" | "restock"
textstring
ctaLabelstringnullable
NameTypeDefaultConstraints
kind"copy"
titlestringnullable
bodystring
NameTypeDefaultConstraints
kind"bundle"
titlestringnullable
bodystringnullable
ctaLabelstringnullable
bundleIdstringnullable

Usage

Replacing how one block kind renders

Write a component for the kind you want to change, here grid. Pass the registry to every RudraComponent that should use it.

import type { ComponentSpec, Product } from '@rudra-js/core';
import { RudraComponent, extendRegistry, type BlockRenderer } from '@rudra-js/react';

const ProductGrid: BlockRenderer<'grid'> = ({ block, context }) => {
  const products = block.items.flatMap((item) => {
    const product = context.products.get(item.sku);
    return product?.isInStock ? [product] : [];
  });

  return (
    <section className="product-grid">
      {block.title && <h3>{block.title}</h3>}
      <ul>
        {products.map((product) => (
          <li key={product.sku}>
            <a href={context.hrefForSku(product.sku)}>{product.title}</a>
            <span>{context.formatPrice(product)}</span>
          </li>
        ))}
      </ul>
    </section>
  );
};

const registry = extendRegistry({ grid: ProductGrid });

export function Recommendations({ spec, products }: { spec: ComponentSpec; products: Product[] }) {
  return <RudraComponent spec={spec} products={products} registry={registry} />;
}

Typed as BlockRenderer<'grid'>, the component gets a block with the grid's fields.

ProductGrid skips any product that is missing or out of stock.

context.hrefForSku and context.formatPrice keep its links and prices the same as the rest of the block.