Share this

Fetching Real Data for Highcharts in React using useEffect

Mustapha Mekhatria Avatar

by

4 minutes read

In the previous post (Dynamic Charts in React using useState with @highcharts/react), I used useState to update a chart with hardcoded data. In this post, I go one step further, fetching real data from an API and rendering it in a chart using useEffect.

This is the pattern behind every real dashboard: data arrives after the component loads, the chart waits, then renders.

What you will build

A line chart that fetches USD to EUR exchange rate historical data from a remote API and renders it automatically when the component mounts.

Prerequisites

  • Node.js installed (node -v to check)
  • Basic knowledge of React

Setting up the project

Create a new React project using Vite:

npm create vite@latest . -- --template react


Install Highcharts:

npm install @highcharts/react

Start the dev server:

npm run dev

Open http://localhost:5173 in your browser.

Your first chart with real data

Open src/App.jsx, delete everything and replace it with:

import { useState, useEffect } from 'react'
import { Chart } from '@highcharts/react'
import { XAxis } from '@highcharts/react'
import { LineSeries } from '@highcharts/react/series/Line'

function App() {
  const [data, setData] = useState([])

  useEffect(() => {
    fetch('https://cdn.jsdelivr.net/gh/highcharts/highcharts@latest/samples/data/usdeur.json')
      .then(response => response.json())
      .then(data => setData(data))
  }, [])

  return (
    <Chart>
      <XAxis type="datetime" />
      <LineSeries data={data} />
    </Chart>
  )
}
export default App

Save the file. You should see a line chart showing USD to EUR exchange rate data.

Adding a loading state

The chart renders an empty state while the data is being fetched. On a fast connection that gap is barely noticeable, but on a slow network or with a large dataset it can leave the user looking at a blank screen.

The fix is a loading state, a simple boolean that controls what the component renders while it waits for the data.Update App.jsx:

import { useState, useEffect } from 'react'
import { Chart } from '@highcharts/react'
import { XAxis } from '@highcharts/react'
import { LineSeries } from '@highcharts/react/series/Line'

function App() {
  const [data, setData] = useState([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    fetch('https://cdn.jsdelivr.net/gh/highcharts/highcharts@latest/samples/data/usdeur.json')
      .then(response => response.json())
      .then(data => {
        setData(data)
        setLoading(false)
      })
  }, [])

  if (loading) return <div>Loading chart data...</div>

  return (
    <Chart>
      <XAxis type="datetime" />
      <LineSeries data={data} />
    </Chart>
  )
}
export default App

The component now shows “Loading chart data…” until the fetch completes, then renders the chart.

What just happened

Three things worth understanding:

1. useEffectruns after the component mounts

useEffect(() => {
  fetch(...)
}, [])

The empty array [] at the end means this effect runs once, when the component first appears on the screen. This is the right place to fetch data.

2. useStatemanages two things

const [data, setData] = useState([])
const [loading, setLoading] = useState(true)

data holds the chart values. loading controls what the user sees while waiting. Both update when the fetch completes.

3. The chart only renders when data is ready

if (loading) return <div>Loading chart data...</div>

This line prevents the chart from rendering with an empty dataset. The user sees a loading message, then the chart appears, clean and predictable.

Why this matters

Most real chart in production follows this pattern. The data does not exist at render time, it arrives from an API, a database, or a WebSocket. useEffect is how you bridge that gap in React.

The loading state is not optional. Without it, your chart renders empty, then jumps to the data, a jarring experience that looks broken even when it is working correctly.In the next post, I will look at rendering large datasets efficiently using the Boost module and useMemo.

Stay in touch

No spam, just good stuff

We're on discord. Join us for challenges, fun and whatever else we can think of
XSo MeXSo Me Dark
Linkedin So MeLinkedin So Me Dark
Facebook So MeFacebook So Me Dark
Github So MeGithub So Me Dark
Youtube So MeYoutube So Me Dark
Instagram So MeInstagram So Me Dark
Stackoverflow So MeStackoverflow So Me Dark
Discord So MeDiscord So Me Dark

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.