How to Master Custom Charts with Recharts: Tips, Tricks, and Pitfalls
This tutorial walks through using Recharts in a React project to build highly customizable pie and bar charts, covering background requirements, library selection criteria, core Recharts features, step‑by‑step implementations of ring‑shaped pies with hover effects, gradient bars with rounded tops, SVG path tricks, and final reflections on abstraction and component choices.
Background
ABCmouse School Edition provides teachers with a module for visualizing student learning data, which requires flexible chart components. After evaluating options, the team chose Recharts because it supports React and offers extensive style customisation.
1. About Recharts
Recharts is a chart library built on React and D3 that redefines how chart elements are combined and configured. Its main characteristics include declarative JSX syntax, native‑like SVG props, and an API that handles complex customisation.
Below is a concise BarChart example that demonstrates Recharts’ simplicity:
<code><BarChart width={520} height={280} data={data}>
<XAxis dataKey="scene" tickLine={false} axisLine={{stroke: "#5dc1fb"}} tick={{fill: "#999"}} />
<Bar dataKey="time" isAnimationActive={!isEmpty} fill="#8884d8" barSize={32} />
</BarChart></code>The library’s design hits all the pain points identified in the requirements.
2. Pie Chart Implementation
The pie chart uses the
PieChartcomponent for the ring, while the centre text and legend are rendered with plain HTML, avoiding extra Recharts configuration.
2.1 Implementing the Ring
The
Piecomponent creates the basic ring, and
Cellsupplies custom colours for each slice.
<code><PieChart width={480} height={400}>
<Pie data={data} dataKey="value" cx={200} cy={200} innerRadius={58} outerRadius={80} fill="#a08bff" stroke="none">
{data.map((entry, index) => (
<Cell key={index} fill={entry.color} />
))}
</Pie>
</PieChart></code>Hovering over a slice expands it and shows a dashed guide line and label. This is achieved with the
activeShapeprop and a custom
renderActiveShapefunction that returns a larger
Sectorelement.
<code><Pie
activeIndex={this.state.activeIndex}
activeShape={renderActiveShape}
data={data}
dataKey="value"
cx={200} cy={200}
innerRadius={58}
outerRadius={80}
fill="#a08bff"
stroke="none"
onMouseEnter={this.onPieEnter}
/></code>The custom shape calculates three points (start, middle, end) using trigonometry, then draws a
Sectorfor the enlarged slice and a
<path>for the guide line:
<code>function renderActiveShape(props) {
const innerOffset = 2;
const outerOffset = 4;
const { cx, cy, innerRadius, outerRadius, startAngle, endAngle, fill } = props;
return (
<Sector
cx={cx}
cy={cy}
innerRadius={innerRadius - innerOffset}
outerRadius={outerRadius + outerOffset}
startAngle={startAngle}
endAngle={endAngle}
fill={fill}
/>
);
}</code>Labels are added with an SVG
<text>element positioned at the end of the guide line.
<code><text x={ex} y={ey} textAnchor="middle" fill="#333">{value}</text></code>2.2 Adding Guide Lines and Labels
Since Recharts does not expose a dedicated guide‑line component, a manual
<path>is used. The
dattribute is built from the three calculated points:
<code><path d={`M${sx},${sy} L${mx},${my} L${ex},${ey}`} stroke={fill} strokeDasharray="1,3" fill="none" /></code>Understanding SVG path commands (M, L, H, V, C, Q, A) was essential, and the article references MDN documentation for further reading.
3. Bar Chart Implementation
The bar chart combines an
XAxiswith a series of custom bars. Gradient fills are added via a
<defs>block containing a
<linearGradient>definition.
<code><BarChart width={520} height={280} data={data}>
<defs>
<linearGradient id="gradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#00ddee" />
<stop offset="100%" stopColor="#5dc1fb" />
</linearGradient>
</defs>
<XAxis dataKey="scene" tickLine={false} axisLine={{stroke: "#5dc1fb"}} tick={{fill: "#999"}} />
<Bar dataKey="time" fill="url(#gradient)" barSize={32} shape={<CustomBar />} label={<CustomLabel />} />
</BarChart></code>3.1 Implementing the Gradient
The gradient is defined inside
<defs>and referenced by the
fillattribute of the
Barcomponent.
3.2 Rounded Top Corners
A custom
CustomBarcomponent draws a path with an arc to create a rounded top. The path uses the bar’s
x,
y,
width, and
heightprops.
<code>function CustomBar({ fill, x, y, width, height }) {
const radius = width / 2;
const d = `M${x},${y + height}
L${x},${y + radius}
A${radius},${radius} 0 0 1 ${x + width},${y + radius}
L${x + width},${y + height}
Z`;
return <path d={d} stroke="none" fill={fill} />;
}</code>3.3 Handling Clipping for Small Values
When a bar’s height is very small, the rounded corner can overflow the chart area. The solution uses SVG
<clipPath>with a deterministic
idpassed to
BarChart, then applied to the custom path:
<code><BarChart id={uniqueId} ...>
...
<path d={d} clipPath={`url(#${uniqueId}-clip)`} ... />
</BarChart></code>3.4 Adding Labels
Labels are rendered with a custom
CustomLabelcomponent that positions a
<text>element above each bar and formats the value.
<code>function CustomLabel({ x, y, width, height, value }) {
return (
<text
x={x + width / 2 - 1}
y={y - 10}
fill="#999"
textAnchor="middle"
className="recharts-text recharts-label"
>
{getStudyTime(value)}
</text>
);
}</code>Summary and Reflections
The author reflects on learning SVG fundamentals, the power of React’s ability to render both HTML and SVG, and the trade‑offs between chart libraries that favour simple configuration (e.g., ECharts) versus those that enable deep customisation (Recharts). The article concludes that choosing the right library depends on the project’s emphasis on flexibility versus ease of use.
References
Recharts – http://recharts.org/
Component‑based Visualisation – https://zhuanlan.zhihu.com/p/20641029
Custom ActiveShape Example – http://recharts.org/en-US/examples/CustomActiveShapePieChart
SVG Tutorial – https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial
Stroke and Fill – https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Fills_and_Strokes
Gradients – https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Gradients
Clipping and Masking – https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Clipping_and_masking
clipPath ID definition – https://github.com/recharts/recharts/blob/master/src/chart/generateCategoricalChart.tsx#L172
React on Embedded LCD – https://juejin.im/post/5dbb729e51882524c101ffe1
SICP Course – https://www.bilibili.com/video/av8515129/
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.