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!
Top comments (5)
Hi, Thank you for your article, it's really helpful!
While, I'm facing an issue now, that is I your method to build my multiple charts and updated all of them at the same time, but then I'm not able to modify my chart canvas when triggering the onHover function in charts, seems it only catch my chartInstance at the initial state, which is null, so then I cannot draw on my chartInstance when hovering on it, could you give an easy example if it is simple for you? Thank you very much!
so far my solution is to create a state for hover event:
cont [hoverEvt, setHoverEvt] = useState(null)
and then in my chart config, I reset state whenever there is hover event:
chartConfig = {
...
options: {
onHover: function(evt) {setHoverEvt(evt)};
}}
And then useEffect() to draw my chart when the state is set:
useEffect(() => {
If(chartInstance != null) {
chartHover(evt, chartInstance);
}
}, [hoverEvt])
function chartInstance(evt, chartInstance) {
(draw my charts...)
}
But I'm thinking of if there is any better solution?
thank you!
Nice post, ty :)
Thanks mate, great help, short precise and helpful
In My project i am implementing this but the options are not applied in the doughnut charts. Can anyone help me out why this is happening.