# SnapshotController

Reactive controller for subscribing to a State container in HTML custom elements

## Import

```ts
import { SnapshotController } from "@videojs/store/html";
```

`SnapshotController` subscribes to a `State` container and triggers host updates when state changes. It has two overloads:

**Full state** – returns the entire state object. Re-renders on any state change.

```ts
class Display extends HTMLElement {
  #state = new SnapshotController(this, sliderState);

  render() {
    const value = this.#state.value;
    // Full state object
  }
}
```

**With selector** – returns a derived value from state. Re-renders only when the selected value changes (using shallow equality).

```ts
class SliderValue extends HTMLElement {
  #value = new SnapshotController(this, sliderState, (s) => s.value);

  render() {
    return this.#value.value; // Only the selected slice
  }
}
```

Use `.track(state)` to switch to a different `State` container at runtime.

### SnapshotController vs StoreController

Both are reactive controllers, but they operate at different levels:

| | `SnapshotController` | [`StoreController`](./store-controller.md) |
| --- | --- | --- |
| **Input** | `State` container | Store instance or context |
| **Subscribes** | Always | Only with a selector |
| **Use case** | Subscribe to raw state changes | Access store actions and optionally subscribe |

`SnapshotController` is lower-level. It works with `State` containers directly – the reactive primitives that back a store. Use it when building custom controllers or working outside the player store system.

[`StoreController`](./store-controller.md) is higher-level. It resolves a store from a context or direct reference and internally creates a `SnapshotController` when you pass a selector. Use it for player UI elements.

### Lifecycle

`SnapshotController` subscribes on `hostConnected()` and unsubscribes on `hostDisconnected()`. The React equivalent is [`useSnapshot`](https://videojs.org/docs/framework/react/reference/api/use-snapshot).

## API Reference

### Without Selector

`new SnapshotController<T extends object, R = T>(host, state)`

#### Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `host` (required) | `{ addController(controller: ReactiveController): void; removeController(controller: ReactiveController): void; requestUpdate(): void; updateComplete: Promise<boolean> }` | — | The host element that owns this controller. |
| `state` (required) | `{ current: Readonly<T>; subscribe(callback: (() => void), options?: SubscribeOptions): (() => void) }` | — | The State container to subscribe to. |

#### Return Value

| Property | Type | Description |
| --- | --- | --- |
| `value` | `R` | |
| `track` | `((state: { current: Readonly<T>; subscribe(callback: (() => void), options?: SubscribeOptions): (() => void) }) => void)` | Switch to tracking a different state container. |

### With Selector

`new SnapshotController<T extends object, R = T>(host, state, selector)`

#### Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `host` (required) | `{ addController(controller: ReactiveController): void; removeController(controller: ReactiveController): void; requestUpdate(): void; updateComplete: Promise<boolean> }` | — | The host element that owns this controller. |
| `state` (required) | `{ current: Readonly<T>; subscribe(callback: (() => void), options?: SubscribeOptions): (() => void) }` | — | The State container to subscribe to. |
| `selector` (required) | `{ (state: T): R; displayName?: string }` | — | Derives a value from the state. |

#### Return Value

| Property | Type | Description |
| --- | --- | --- |
| `value` | `R` | |
| `track` | `((state: { current: Readonly<T>; subscribe(callback: (() => void), options?: SubscribeOptions): (() => void) }) => void)` | Switch to tracking a different state container. |