Start at Mike Bostock's Towards Reusable Charts.
I’d like to propose a convention for encapsulating reusable charts in D3. Wait for it…
A function; the standard unit of code reuse!
Reusable charts are self-contained functions.
They have a defined "API" that's passed configuration options through getter-setter methods.
// A function encapsulating all your chart logic
import ReusableChart from 'my-reusable-chart';
// Create a new instance of the chart
const myChart = ReusableChart();
// Set some configuration
myChart.height(300);
myChart.width(600);
// (...also, get configuration)
myChart.height();
// 300
// Draw it
d3.select('#chart').call(myChart);
Component charts are just reusable charts that are guaranteed to render idempotently.
"Idempotence" just means we can call the chart function over and over and the chart will only change/re-render when it's passed new configuration like this:
({ height, width }) => < Renders >
({ height, width }) => # nothing
({ height, width }) => # nothing
({ newHeight, width }) => < Re-Renders >
({ newHeight, width }) => # nothing
🔑 Idempotence is the key to integrating with reactive frameworks.