loading...

Using Chart.js in a function component with React hooks

vcanales profile image Vicente Canales ・2 min read

Why

When using React in conjunction with other JavaScript libraries, it's common to see that React-specific versions of those libraries exist. Regardless of whether they exist to make parts of those libraries available as components, or to aid the developer in making React play nice with a particularly intricate library, I think this is not the case for Chart.js.

Initialization

If we take advantage of React's useRef hook, we can make use of Chart.js without the need for a made-for-react version of it. The key snippet looks like this:

import React, { useEffect, useRef } from 'react';
import Chartjs from 'chart.js';

const chartConfig = {
  type: 'bar',
  data: {
    // ...
  },
  options: {
    // ...
  }
};

const Chart = () => {
  const chartContainer = useRef(null);
  const [chartInstance, setChartInstance] = useState(null);

  useEffect(() => {
    if (chartContainer && chartContainer.current) {
      const newChartInstance = new Chartjs(chartContainer.current, chartConfig);
      setChartInstance(newChartInstance);
    }
  }, [chartContainer]);

  return (
    <div>
      <canvas ref={chartContainer} />
    </div>
  );
};

export default Chart;

Chart.js uses the DOM Canvas to render, and the ctx parameter in new Chartjs(ctx, options) is a reference to the <canvas /> element where we'll mount our chart.

They key takeaway from this is that the useRef hook allows us to use an effect to initialize our chart as soon as the DOM object is available, by reacting to changes on the chartContainer ref variable.

After initialization

On initialization, we're assigning the initialized chart to the chartInstance state variable so that we can update our chart later, like this:

  const updateDataset = (datasetIndex, newData) => {
    chartInstance.data.datasets[datasetIndex].data = newData;
    chartInstance.update();
  };

  const onButtonClick = () => {
    const data = [1, 2, 3, 4, 5, 6];
    updateDataset(0, data);
  };

This updates the Chart after the callback for a button click is invoked, but this could also be done inside a useEffect callback, or really anywhere else where you have access to chartInstance.

There, short but sweet little tip!

PS. Check out the working version on codesandbox.io!

Posted on by:

Discussion

markdown guide