Skip to content
Twilight React Playground
ثيم رائدaren

useComponent

hookBeginnerserverbrowserlive demo

Return the component registered under a name, or the one it replaced, so you render it yourself with typed props.

import { useComponent, useOriginalComponent } from '@salla.sa/twilight-theme-engine';

In plain words

Where <Component name=…> renders for you, useComponent(name) hands you the component itself, or null. That helps when you want typed props or need to decide how to render.

useOriginalComponent(name) returns the component that was stored under the name before the last override, or null when nothing was overridden.

Signature

function useComponent<P = Record<string, unknown>>(name: string): ComponentType<P> | null
function useOriginalComponent<P = Record<string, unknown>>(name: string): ComponentType<P> | null

Try it live

Both hooks read the same registry key: useComponent gives the current component, useOriginalComponent the one it replaced.Try this: switch "overridden" on: the original becomes the plain badge the theme registered first.
Storefront canvas · en · LTR
Runs in the browser…
Controls
overriddenCalls registry.override() with a second badge.
What a theme writes
import { useComponent, useOriginalComponent } from '@salla.sa/twilight-theme-engine';

type BadgeProps = { text: string };

export function BadgeCompare() {
  const Current = useComponent<BadgeProps>('my-theme:badge');
  const Original = useOriginalComponent<BadgeProps>('my-theme:badge');
  // No override yet: Original is null.
  return (
    <>
      {Current && <Current text="New" />}
      {Original && <Original text="New" />}
    </>
  );
}

Example

app/components/FeaturedCard.tsx
import { useComponent } from '@salla.sa/twilight-theme-engine';
import type { ProductCardProps } from '@salla.sa/twilight-theme-engine/components/product';

export function FeaturedCard(props: ProductCardProps) {
  const Card = useComponent<ProductCardProps>('my-theme:featured-card');
  return Card ? <Card {...props} /> : null;
}

How it behaves

  • Both are plain reads (registry.resolve and registry.getOriginal) with no React state: registering or overriding later re-renders nothing.

  • getOriginal goes back one step: override A with B, then B with C, and the original is B.

  • The engine itself calls useComponent('account:layout-pending') for the account layout's loading state and falls back to its own skeleton.

Gotchas

  • override is not idempotent. Running the same override twice (a module evaluated twice, a hot reload) stores the first override as the original of the second, so useOriginalComponent returns your own override. Keep registration in one module that runs once, or call register before override to reset the key.

  • useOriginalComponent('product:card') inside a card override renders that override again, forever: the engine's default card is never registered (see registry).

Related

Source and docs