0

I currently have a Radar chart in chart.js using the react integration.

I was suprised to note that, when I updated the data, instead of showing a completely new plot, it just transitioned smoothly from the previous dataset to the new one.

What I am interested in is to understand how it works under the hood, which honestly I can't understand, at least from looking at the code.

First: my understanding of React is that, when a prop or state changes, it computes the new DOM, and then merges the new DOM and the current DOM, applying only the difference between the two. However, chartjs seem to be implemented as a Canvas element.

The chartjs integration with react does not do much. Taking the Radar plot, this is what it does

export const Radar = /* #__PURE__ */ createTypedChart('radar', RadarController);

which is nothing but declare a <Chart> element and leave it to ChartJS to plot it. In fact, in ChartJS, we have this code, which basically manages the Canvas element and it is smart to perform transitions using animations and so on. This I understand (relatively): a lot of animation and transition helper functions, but this makes sense to me. However, this part is pure JavaScript. There's nothing that is aware of React.

What does not make sense is therefore how the react synchronization system is integrated with this JavaScript library so that the state invalidation of the props/state is synchronised to an animation, instead of a complete rewrite of the Canvas element. I don't seem to find where this magic happens in react-chartjs-2.

Stefano Borini
  • 138,652
  • 96
  • 297
  • 431

3 Answers3

2

As you explained the canvas element does not get changed so it gets reused. To animate the chart chart.js itself has an update method. React-chartjs-2 uses a useeffect function that checks if the data you pass it has changed. If this is the case it calls the update function from chart.js itself and they handle the animations and updates itself:

  useEffect(() => {
    if (!chartRef.current) return;

    if (redraw) {
      destroyChart();
      setTimeout(renderChart);
    } else {
      chartRef.current.update();
    }
  }, [redraw, options, data.labels, data.datasets]);

https://github.com/reactchartjs/react-chartjs-2/blob/4a010540ac01b1e4b299705ddd93f412df4875d1/src/chart.tsx#L78-L87

LeeLenalee
  • 27,463
  • 6
  • 45
  • 69
1

You can see here: https://github.com/reactchartjs/react-chartjs-2/blob/master/src/chart.tsx

The react-chartjs-2 library creates a component that adds a canvas and when the props update the component creates/updates an internal Chart object that uses the rendered canvas.

From what I saw the animation starts when the props are changed.

The path is props->react-chartjs-2 component->chart object->animation

1

This is my understanding of the whole process after diving into the code base quite a bit. I've tried to be as detailed as possible with links to the exact line of code I am talking about. Hope this helps:

  1. Beginning with the code snippet you shared:

    export const Radar = /* #__PURE__ */ createTypedChart('radar', RadarController);

  2. If you follow the RadarController via the import statement, you see that it is fetched from chart.js

  3. Now we move to the Chart.js code and look for this controller RadarController. It is found in a file called src/controllers/controller.radar.js.

  4. Within that file, you see an update function

  5. This function then calls updateElements with the points information

  6. This function gets the new point position which is then set in properties and passed into the updateElement function

  7. This updateElement function directly takes us to the core.datasetController

  8. Here you see a condition to check if the chart is in directUpdateMode. If not, it calls a function to _resolveAnimations

  9. Within this function, you will see the new Animations(args) object

  10. This eventually brings us to the core.animations file which consists of all the animation related information and processing.

  11. One interesting bit I found here was: this is what seems to be making the beautiful movement of points to the changed location.

  12. You can explore this Animations class further for more detailed understanding

So yeah essentially, it is the js part under the hood that facilitates the smooth transitions and this is how it does it. React code is essentially just like a wrapper of Chart.js calling this update method with the new values.

Aneesh
  • 1,720
  • 4
  • 14