# Live Data and View State

> Live Data and View State: anatomy, keyboard behavior, state, and theming in Askr.

Source: [https://askrjs.com/docs/charts/live-and-view-state](https://askrjs.com/docs/charts/live-and-view-state)

Status: stable. Packages: @askrjs/askr.

**Published packages are authoritative.** Examples may lag behind a published contract. When guidance differs, verify the exports and TypeScript declarations in your installed package, then file an issue.

## Example

```tsx
import { state } from '@askrjs/askr';
import { createPlot, type PlotView } from '@askrjs/charts';

const Plot = createPlot<MetricRow>();

function LiveLatency() {
  const [view, setView] = state<PlotView>({});
  return <Plot.Root
    data={rows()}
    rowKey="id"
    label="Live latency"
    view={view()}
    onViewChange={setView}
    followLatest={{ durationMs: 300_000, field: 'timestamp' }}
  ><Plot.Line x="timestamp" y="latencyMs" /></Plot.Root>;
}
```

## Append and upsert

`appendPlotRows(rows, additions)` adds one or many rows to the end of an array without mutating the original. `upsertPlotRows(rows, updates, rowKey)` replaces any row whose key matches an update and appends the rest, and rejects duplicate keys within the update batch itself — both return a frozen result, or the original array when nothing actually changed.

## Trim rows

`trimPlotRows(rows, options)` keeps a live array from growing without bound. Pass a plain number (or `{ rows: N }`) to retain the latest N rows by position, or `{ durationMs, field, now? }` to retain only rows whose `Date` field falls within a trailing time window — the natural pairing for a plot that's also using `followLatest`.

## Follow latest

`Root`'s `followLatest` prop accepts a bare number as row-count shorthand, `{ rows: N }`, or `{ durationMs, field }` for a time-based window, and keeps the visible view pinned to the newest data as it arrives. Any user pan or zoom pauses following immediately, and it stays paused — even as more rows come in — until the app calls `PlotApi.resumeLive()`, so an operator inspecting an anomaly is never yanked back to "now" mid-investigation.

## Controlled view

`PlotView` holds optional `x` and `y` domain tuples plus a `scales` map for named coordinate scales; `x`/`y` are shorthand aliases for the primary scales, and an entry in `scales` takes precedence for that specific scale. Use `defaultView` when the view can live entirely inside the plot, or `view` together with `onViewChange` when a URL, route, or sibling control needs to own and synchronize the visible domain.

## Documentation navigation

[Previous](https://askrjs.com/docs/charts/interactions/index.md) | [Next](https://askrjs.com/docs/charts/export/index.md)
