Real-time TradingView Charts in dApps with React

Integrating TradingView Lightweight Charts into a dApp When building a dApp with crypto charts, developers often face a dilemma: the library must be lightweight yet performant. TradingView Lightweight Charts solves this, but integrating with on-chain data requires care. Initialization mistakes ca

Blockchain Development Services

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1452
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1309
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    1005
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1270
  • image_logo-advance_0.webp
    B2B Advance company logo design
    719
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    1011

Integrating TradingView Lightweight Charts into a dApp

When building a dApp with crypto charts, developers often face a dilemma: the library must be lightweight yet performant. TradingView Lightweight Charts solves this, but integrating with on-chain data requires care. Initialization mistakes can lead to memory leaks up to 200 MB within an hour of dApp runtime. Our Web3 engineering team has integrated this library into dozens of decentralized applications — from simple dashboards to full-fledged trading interfaces with real-time updates. We know the pitfalls of connecting on-chain data and how to avoid them to keep the chart stable even under high load. Proper integration can cut RPC infrastructure costs by up to 50%.

How to Initialize TradingView Lightweight Charts Without Memory Leaks

import { createChart, IChartApi, CandlestickData } from 'lightweight-charts'; const chartContainer = useRef<HTMLDivElement>(null); const chartRef = useRef<IChartApi>(); useEffect(() => { if (!chartContainer.current) return; const chart = createChart(chartContainer.current, { width: chartContainer.current.clientWidth, height: 400, layout: { background: { color: '#0d0d0d' }, textColor: '#9ca3af', }, grid: { vertLines: { color: '#1f2937' }, horzLines: { color: '#1f2937' }, }, timeScale: { timeVisible: true, secondsVisible: false, }, }); chartRef.current = chart; return () => chart.remove(); }, []); 

Always call chart.remove() in the cleanup function of useEffect; otherwise, hot reloads or unmounting accumulate memory leaks. This is one of the most common mistakes we see. Skipping the cleanup causes memory usage to grow to over 200 MB in an hour of dApp operation.

How to Update On-Chain Data in Real-Time Without Performance Loss

The main challenge when integrating into a dApp is fetching OHLCV candles. On-chain data can be retrieved from several sources. Here’s a comparison:

Data Source Latency Integration Complexity dApp Load
Subgraph (The Graph) ~30 sec Medium (requires GraphQL query) Low
WebSocket (RPC subscription) ~1–2 sec High (needs backend aggregator) Medium
Direct RPC polling ~10–15 sec Low (simple request) High (RPC limits)

Subgraph is the most common choice for DEXs. Uniswap v3 subgraph provides poolHourDatas and poolDayDatas with OHLC per pool. Query:

query GetCandles($pool: String!, $startTime: Int!) { poolHourDatas( where: { pool: $pool, periodStartUnix_gte: $startTime } orderBy: periodStartUnix first: 1000 ) { periodStartUnix open high low close volumeUSD } } 

Conversion to LWC format:

const candles: CandlestickData[] = data.poolHourDatas.map((d) => ({ time: d.periodStartUnix as UTCTimestamp, open: parseFloat(d.open), high: parseFloat(d.high), low: parseFloat(d.low), close: parseFloat(d.close), })); candleSeries.setData(candles); 

Real-time updates — poll the subgraph every 30–60 seconds or subscribe to Swap events via WebSocket RPC. On receiving a new event, recalculate the current (unclosed) candle and update via candleSeries.update(newCandle) instead of setData (full data reset on every tick kills performance). We recommend combining subgraph for historical data and WebSocket for real-time — this gives the best balance of speed and load. Such a scheme reduces RPC calls by 90%.

Lightweight Charts is 1.5–2x faster than Chart.js on sets of 1000 candles (60 FPS vs 30–40 FPS), which is critical for real-time trading.

How to Synchronize Multiple TradingView Charts in Real-Time

If you need two charts in sync (e.g., price + volume), use chart.timeScale().subscribeVisibleTimeRangeChange() to synchronize the viewport between instances. Common practice for trading interfaces:

chart1.timeScale().subscribeVisibleTimeRangeChange((range) => { if (range) chart2.timeScale().setVisibleRange(range); }); 

Responsive Resizing

LWC does not automatically adapt to container size changes. Use ResizeObserver:

const resizeObserver = new ResizeObserver(entries => { const { width, height } = entries[0].contentRect; chart.applyOptions({ width, height }); }); resizeObserver.observe(chartContainer.current); 

Custom Markers and Overlays

To display on-chain events over the chart (e.g., liquidations, large trades), use series.setMarkers(). Markers render directly on candles and don't require custom canvas rendering — much simpler than implementing overlays manually.

Comparison of Lightweight Charts with Alternatives

Library Size (gzip) Performance (FPS at 1000 candles) Customization
Lightweight Charts ~45 KB 60 Full customization
Chart.js ~70 KB 30–50 Medium
D3.js ~30 KB (core) 20–40 (custom render) Complex

Lightweight Charts delivers 1.5–2x higher frame rates on large datasets, crucial for real-time trading interfaces. More details can be found in the Lightweight Charts GitHub repository.

Work Process for Integration

  1. Analyze the current dApp and data sources (on-chain, subgraph, RPC).
  2. Design architecture: select source, configure real-time updates, caching.
  3. Develop: integrate the library, style to dApp brand, connect data.
  4. Test: verify against various scenarios (high volume, low liquidity, errors).
  5. Deploy and monitor: set up logging, alerting on desync.

Timeline: 5 to 15 business days depending on complexity (number of charts, data types, need for backend sync). Cost is calculated individually after analyzing your dApp. Request a consultation — we'll find the optimal solution.

What's Included in the Work

  • Implementation of a custom chart component for React/Vue/Next.js.
  • Data feed setup (Subgraph, RPC, WebSocket).
  • Performance optimization (candle caching, update debouncing).
  • Synchronization of multiple charts and on-chain event markers.
  • Integration documentation and post-deployment support.

We bring 5+ years of Web3 development experience and 20+ successful integrations with DEX and DeFi protocols. We guarantee stable chart performance under high load. Contact us — we'll analyze your dApp and propose a solution.

Common Mistakes When Integrating Lightweight Charts into a dApp

  • Ignoring cleanup: not calling chart.remove() in useEffect cleanup — memory leak.
  • Overwriting data with setData on every update: use update for the last candle.
  • Missing ResizeObserver: chart doesn't adapt when window resizes.
  • Incorrect timestamp conversion: ensure time is passed as UTCTimestamp.
  • Synchronizing multiple charts without subscribeVisibleTimeRangeChange.

We fix these mistakes in almost every second project, so we include them in our standard checklist.