Concorde documentation (crawl) · interactive version

Concorde decorator — @subscribe. Keeps a Lit property in sync with a read-only slice of the DataProvider store. You pass a DataProviderKey; when that path changes, the property updates and the component re-renders. Doc ID: docs/_decorators/subscribe. Keywords: Concorde, supersoniks, docs/_decorators/subscribe, subscribe, @subscribe, decorator, DataProviderKey, | Shape of the object at that path (, , , , …) | | **Key** | , — static path (, ) or dynamic (, (e.g. , ) — often filled via [. URL: https://concorde.supersoniks.org/crawl/docs/_decorators/subscribe.html.

@subscribe

Keeps a Lit property in sync with a read-only slice of the DataProvider store. You pass a DataProviderKey; when that path changes, the property updates and the component re-renders.

Typical setup (same idea as My first component):

Piece Role
Type T Shape of the object at that path (DocsUserData, { count: number }, …)
Key DataProviderKey<T, U> — static path ("cart") or dynamic ("users.${userIndex}", "${dataProvider}")
Scope on the host Properties listed in U (e.g. dataProvider, userIndex) — often filled via @ancestorAttribute
@subscribe(key) Mirrors the store into @state() (or another property); read-only from the component side

For writing back to the store from component state, use @publish. In templates, the same paths work with sub().

Import

import { subscribe } from "@supersoniks/concorde/decorators";
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";

type Data = { count: number };
const dataKey = new DataProviderKey&lt;Data&gt;("data");

@subscribe(dataKey.count)
@state()
count = 0;

Static path

The key path is fixed. The property type must match T at that segment.

const cartKey = new DataProviderKey&lt;{ items: string[] }&gt;("cart");

@subscribe(cartKey)
@state()
cart: { items: string[] } | null = null;

Dynamic path and scope

Placeholders ${prop} in the key string are resolved from properties on the same component. While a value is null/undefined, the subscription is inactive; optional { skipEmptyPlaceholder: true } also waits on "". Full rules: Dynamic path placeholders.

Declare dynamic props in the key’s second generic so TypeScript expects them on the host:

type User = { firstName: string; lastName: string; email: string };

@subscribe(new DataProviderKey&lt;User, { userIndex: number }&gt;("demoUsers.${userIndex}"))
@state()
user: User | null = null;

@property({ type: Number }) userIndex = 0;

When userIndex changes, @subscribe re-resolves the path and refreshes user.

Row / ancestor scope

List items (and wrappers like <div dataProvider="…">) set which branch the child reads. Pattern from the tutorial:

export const rowKey = new DataProviderKey&lt;
  User,
  { dataProvider: string | null }
&gt;("${dataProvider}");

@ancestorAttribute("dataProvider")
dataProvider: string | null = null;

@subscribe(rowKey)
@state()
user: User | null = null;

Demo

<docs-demo-sources for="demo-subscribe-dynamic"></docs-demo-sources>
    <demo-subscribe-dynamic></demo-subscribe-dynamic>

See also