A chart should absorb live ticks without remounting — repainting the canvas at 60fps in React, Vue or Svelte. Two ways to push live ticks in — pick one below to walk through it:
- Declarative — keep the series in state and hand it to the
dataprop; the wrapper diffs it and appends, updates, or rolls the window for you. - Imperative — call
appendData/updateData/keepLaston the chart instance directly.
01 — UPDATE THE DATA PROP
Keep the series array in state and pass it to the series
data prop. On every change the wrapper diffs the new array against the previous one and picks the cheapest mutation — append, update-in-place, roll, or bulk-replace. The live chart runs exactly this.const [data, setData] = useState(seed); useEffect(() => { const id = setInterval(() => { setData((prev) => [...prev, nextBar(prev)].slice(-120)); }, 1000); return () => clearInterval(id);}, []); return <CandlestickSeries id="price" data={data} />;02 — APPEND A BAR vs UPDATE THE FORMING ONE
The diff keys on timestamps. A point with a new time is appended — a fresh candle with its entrance animation. Replacing the last point (same time, new OHLC) updates it in place, the body and wick easing over
smoothMs. A feed updates the forming bar each tick, then appends when it closes.setData((prev) => { const last = prev[prev.length - 1]; // same timestamp → update in place (eases via smoothMs) if (sameBar) return [...prev.slice(0, -1), { ...last, high, low, close }]; // new timestamp → append (entrance animation) return [...prev, { time: last.time + interval, open: last.close, high, low, close }];});03 — ROLLING WINDOW & AUTO-SCROLL
Cap the buffer with
.slice(-n). Unlike a full setSeriesData, trimming eases the Y axis instead of snapping, so the window rolls without jitter. Auto-scroll keeps the newest bar pinned to the right until the reader pans away. The same data prop drives Vue and Svelte.