> ## Documentation Index
> Fetch the complete documentation index at: https://react-native-livechart.brandtnewlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# States & formatting

> Loading and empty states, and worklet-safe value/time formatters.

Before data arrives — or when a feed runs dry — the chart shows a placeholder instead of a blank
plot. These props control those states and the text the chart renders.

<Note>
  **Live example:**
  [`app/demo/states-and-formatting.tsx`](https://github.com/brandtnewlabs/react-native-livechart/blob/main/app/demo/states-and-formatting.tsx)
  in the example app.
</Note>

<Frame caption="Loading and empty placeholders, plus custom value/time formatters">
  <video autoPlay loop muted playsInline controls poster="/media/states-and-formatting.jpg" src="https://mintcdn.com/brandtnewlabs/3aK_iydbC8Ff9g3s/media/states-and-formatting.mp4?fit=max&auto=format&n=3aK_iydbC8Ff9g3s&q=85&s=9bd66af741b1e03ef892d12d10204ee3" data-path="media/states-and-formatting.mp4" />
</Frame>

## Loading

While you wait for data, pass `loading` to render a breathing-line placeholder.

```tsx theme={null}
<LiveChart data={data} value={value} loading={!ready} />
```

### Styling the loading shell

`loading` also takes a `LoadingConfig` object to restyle the shell — the squiggle and the skeleton
Y-axis placeholders. Every field is optional:

```tsx theme={null}
<LiveChart
  data={data}
  value={value}
  loading={
    !ready && {
      color: "#64748b",   // squiggle + skeleton color (default: theme gridLine)
      strokeWidth: 3,      // squiggle thickness (default: the chart line width)
      amplitude: 22,       // breathing-wave height in px (default: 14)
      speed: 1.5,          // wave cadence (default: 1; 0 freezes the wave)
      axisLabels: false,   // hide the skeleton Y-axis placeholders (default: true)
    }
  }
/>
```

Pass `true` for the defaults, the object to restyle, and `false` (or omit) for "not loading" — so
`loading={!ready && cfg}` toggles the styled shell as data arrives. Set `axisLabels: false` to drop the
skeleton Y-axis placeholders and show only the breathing squiggle. `color`, `amplitude`, and `speed`
also flow into the brief reveal morph, so the squiggle keeps its look as it melts into the line. The
same config works on `LiveChartSeries`. The loading→live reveal duration itself is controlled by the
[`transitions.reveal`](/guides/transitions) prop.

## Empty state

When there are fewer than two samples and `loading` is `false`, the chart shows an empty shell
with a label. Customize the label with `emptyText`.

```tsx theme={null}
<LiveChart data={data} value={value} emptyText="Waiting for trades…" />
```

## Formatting values & time

`formatValue` and `formatTime` control the text on axes, the badge, and tooltips. They run on the
UI thread, so **they must be worklet-safe** — mark them with the `"worklet"` directive and keep
them pure (no JS-thread closures).

```tsx theme={null}
<LiveChart
  data={data}
  value={value}
  formatValue={(v) => {
    "worklet";
    return `$${v.toFixed(2)}`;
  }}
  formatTime={(t) => {
    "worklet";
    const s = Math.floor(t) % 60;
    const m = Math.floor(t / 60) % 60;
    const pad = (n: number) => (n < 10 ? `0${n}` : `${n}`);
    return `${pad(m)}:${pad(s)}`;
  }}
/>
```

<Tip>
  The library also exports worklet-safe
  [`formatValue` / `formatTime`](/api-reference/hooks-and-utilities) helpers (adaptive `K` / `M`
  suffixes and `HH:MM:SS`) you can pass directly or call from your own formatters.
</Tip>
