Best Practices for Code Organization
As a software engineer, making graphs responsive is a common task. You’ll likely apply this approach across all chart components in your codebase.
Let’s explore a useful convention I like to use in my work to simplify this process.
🎁 Wrapper component
I like to create a "wrapper" component that manages the responsiveness and pass all the other props to the viz component, plus width
and height
.
If the graph component is called let's say DensityChart
, I like calling the wrapper ResponsiveDensityChart
.
Here is the organization I usually use:
type ResponsiveDensityChartProps = {
data: number[];
};
// Responsive component = wrapper that manages the dimensions and does nothing else
export const ResponsiveDensityChart = (props: ResponsiveDensityChartProps) => {
const chartRef = useRef(null);
const chartSize = useDimensions(chartRef);
return (
<div ref={chartRef} style={{ width: '100%', height: '100%' }}>
<DensityChart
height={chartSize.height}
width={chartSize.width}
{...props} // pass all the props
/>
</div>
);
};
// Type is the same, with width and height added!
type DensityChartProps = ResponsiveDensityChartProps & {
width: number;
height: number;
};
// Non responsive component
const DensityChart = ({ width, height, data }: DensityChartProps) => {
//... dataviz code goes here
}
Why It’s Great:
🚃 Seamless Prop Forwarding
Using the ...props
notation, all props are automatically passed to the child component, streamlining component configuration and usage.
TypeScript Support
With the &
operator, there’s no need to re-type both the main chart component and its responsive variant. The responsive component has the same type as the chart component, with the addition of width and height props.
Consistency Across Components
For codebases with multiple chart components, consistently using this wrapper approach minimizes mental overhead, making it easier to manage and scale your components.