# @subscribe

`@subscribe(key)` keeps a component property in sync with one path of the store: when a publisher assigns that path, the property updates and the component re-renders. It is read-only; use [@publish](/docs/decorators/publish) to write and [sub()](/docs/directives/sub) to read inside a template. See [Data flow](/docs/getting-started/dataFlow) for the overall model.

## Import

<sonic-code language="typescript">
  <template>
import { subscribe } from "@supersoniks/concorde/decorators";
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";

type Cockpit = { altitude: number };
const cockpitKey = new DataProviderKey&lt;Cockpit&gt;("cockpit");

@subscribe(cockpitKey.altitude)
@state()
altitude = 0;
  </template>
</sonic-code>

## Static path

The key is a [DataProviderKey](/docs/misc/dataProviderKey): the property type must match `T` at that path. Add `@state()` so Lit re-renders. Until the publisher holds a value, the property keeps its initializer.

<sonic-code language="typescript">
  <template>
type Flight = { code: string; gate: string; status: string };
const flightKey = new DataProviderKey&lt;Flight&gt;("flight");

@subscribe(flightKey)
@state()
flight: Flight | null = null;
  </template>
</sonic-code>

## Dynamic path

`${prop}` placeholders resolve from properties of the same component. Declare them in the key's second generic so TypeScript requires them on the host. When `seatIndex` changes, the path is resolved again and `person` refreshes; while the placeholder is `null` or `undefined`, the subscription is inactive. Resolution rules: [Dynamic paths](/docs/misc/dynamic-path).

<sonic-code language="typescript">
  <template>
type OnBoard = { name: string; role: string; seat: string };
const personKey = new DataProviderKey&lt;OnBoard, { seatIndex: number }&gt;(
  "demoOnBoard.${seatIndex}",
);

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

@subscribe(personKey)
@state()
person: OnBoard | null = null;
  </template>
</sonic-code>

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

## Ancestor scope

Inside a list row or a `dataProvider` wrapper, read the path from the closest ancestor with [@ancestorAttribute](/docs/decorators/ancestor-attribute), then use it as the placeholder.

<sonic-code language="typescript">
  <template>
const rowKey = new DataProviderKey&lt;OnBoard, { dataProvider: string | null }&gt;(
  "${dataProvider}",
);

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

@subscribe(rowKey)
@state()
person: OnBoard | null = null;
  </template>
</sonic-code>

## API reference

| Argument | Type | Description |
|----------|------|-------------|
| `key` | `DataProviderKey<T, U>` | Path to read. `U` lists the host properties used by `${…}` placeholders |

The decorated property is typed `T` (optionally `| null` or `| undefined`). The subscription starts when the component connects and stops when it disconnects.
