Columns in React

Using ApexCharts with React

This Columns example wires ApexCharts into React through the react-apexcharts component.

Install it with npm install react-apexcharts apexcharts, then mount the chart with <Chart type="..." options={options} series={series} />.

React charts guide
import React from 'react'
import ReactApexChart from 'react-apexcharts'
import ApexCharts from 'apexcharts'
import './styles.css'

import 'apexcharts/features/highlight-filter'

// Shared by the vanilla-js, React and Vue builds.
//
// Units sold per year by region (the wholes), and what each sales channel
// contributed to them (the parts). Picking a channel keeps every year and
// region on the chart: each column is drawn faded at its full value, with the
// channel's share solid in front.
var YEARS = ['2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022']
var REGIONS = ['Americas', 'Europe', 'Asia Pacific']
var UNITS = [
  [34, 43, 66, 69, 58, 40, 78, 80],
  [21, 26, 29, 32, 47, 46, 50, 96],
  [19, 24, 28, 26, 38, 31, 52, 38],
]
var CHANNELS = {
  online: [
    [26, 29, 50, 48, 37, 26, 55, 40],
    [14, 17, 21, 20, 23, 34, 38, 70],
    [12, 18, 22, 20, 26, 21, 38, 19],
  ],
  store: [
    [8, 14, 16, 21, 21, 14, 23, 40],
    [7, 9, 8, 12, 24, 12, 12, 26],
    [7, 6, 6, 6, 12, 10, 14, 19],
  ],
}

function seriesFor(channel) {
  return REGIONS.map(function (name, i) {
    var s = { name: name, data: UNITS[i] }
    if (channel) s.highlightData = CHANNELS[channel][i]
    return s
  })
}

// One call per pick: the parts go in, the chart animates from what is on
// screen. Clearing is the same call without them.
function pickChannel(chart, channel) {
  document.querySelectorAll('[data-channel]').forEach(function (b) {
    b.classList.toggle('active', b.getAttribute('data-channel') === channel)
  })
  return chart.updateSeries(seriesFor(channel))
}

function wireChannels(chart) {
  document.querySelectorAll('[data-channel]').forEach(function (b) {
    b.addEventListener('click', function () {
      pickChannel(chart, b.getAttribute('data-channel'))
    })
  })
}

const ApexChart = () => {
  const [state, setState] = React.useState({
    series: seriesFor('online'),
    options: {
      chart: {
        id: 'units',
        type: 'bar',
        height: 380,
        toolbar: { show: false },
      },
      colors: ['#16a34a', '#f59e0b', '#2563eb'],
      plotOptions: {
        bar: { columnWidth: '78%' },
      },
      dataLabels: { enabled: false },
      stroke: { show: true, width: 1, colors: ['transparent'] },
      xaxis: { categories: YEARS },
      yaxis: { title: { text: 'Units (thousands)' } },
      highlightFilter: { fadeOpacity: 0.2 },
      legend: { position: 'bottom' },
      tooltip: { shared: true, intersect: false },
    },
  })

  React.useEffect(() => {
    // The react-apexcharts wrapper owns the render, so reach the live instance
    // by its chart.id. (seriesFor / pickChannel live in the shared head script.)
    const timer = window.setInterval(() => {
      const chart = ApexCharts.getChartByID('units')
      if (!chart) return
      window.clearInterval(timer)
      wireChannels(chart)
    }, 50)
    return () => window.clearInterval(timer)
  }, [])

  return (
    <div>
      <div className="wrap">
        <h1>Highlight a part of every column</h1>
        <p>
          Pick a sales channel. Every column stays on the chart at its full
          value, faded, and the part that channel sold is drawn solid in front
          of it from the same baseline. Labels and tooltips state the part.
        </p>
        <div className="actions">
          <span>Channel</span>
          <button data-channel="online" className="active">
            Online
          </button>
          <button data-channel="store">In store</button>
          <button data-channel="">All (clear)</button>
        </div>
        <div className="chart-wrap">
          <div id="chart">
            <ReactApexChart
              options={state.options}
              series={state.series}
              type="bar"
              height={380}
            />
          </div>
        </div>
      </div>
    </div>
  )
}

export default ApexChart