Frontend Development 18 min read

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.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
How to Master Custom Charts with Recharts: Tips, Tricks, and Pitfalls

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>&lt;BarChart width={520} height={280} data={data}&gt;
  &lt;XAxis dataKey="scene" tickLine={false} axisLine={{stroke: "#5dc1fb"}} tick={{fill: "#999"}} /&gt;
  &lt;Bar dataKey="time" isAnimationActive={!isEmpty} fill="#8884d8" barSize={32} /&gt;
&lt;/BarChart&gt;</code>

The library’s design hits all the pain points identified in the requirements.

2. Pie Chart Implementation

The pie chart uses the

PieChart

component for the ring, while the centre text and legend are rendered with plain HTML, avoiding extra Recharts configuration.

2.1 Implementing the Ring

The

Pie

component creates the basic ring, and

Cell

supplies custom colours for each slice.

<code>&lt;PieChart width={480} height={400}&gt;
  &lt;Pie data={data} dataKey="value" cx={200} cy={200} innerRadius={58} outerRadius={80} fill="#a08bff" stroke="none"&gt;
    {data.map((entry, index) => (
      &lt;Cell key={index} fill={entry.color} /&gt;
    ))}
  &lt;/Pie&gt;
&lt;/PieChart&gt;</code>

Hovering over a slice expands it and shows a dashed guide line and label. This is achieved with the

activeShape

prop and a custom

renderActiveShape

function that returns a larger

Sector

element.

<code>&lt;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}
/&gt;</code>

The custom shape calculates three points (start, middle, end) using trigonometry, then draws a

Sector

for the enlarged slice and a

&lt;path&gt;

for the guide line:

<code>function renderActiveShape(props) {
  const innerOffset = 2;
  const outerOffset = 4;
  const { cx, cy, innerRadius, outerRadius, startAngle, endAngle, fill } = props;
  return (
    &lt;Sector
      cx={cx}
      cy={cy}
      innerRadius={innerRadius - innerOffset}
      outerRadius={outerRadius + outerOffset}
      startAngle={startAngle}
      endAngle={endAngle}
      fill={fill}
    /&gt;
  );
}</code>

Labels are added with an SVG

&lt;text&gt;

element positioned at the end of the guide line.

<code>&lt;text x={ex} y={ey} textAnchor="middle" fill="#333"&gt;{value}&lt;/text&gt;</code>

2.2 Adding Guide Lines and Labels

Since Recharts does not expose a dedicated guide‑line component, a manual

&lt;path&gt;

is used. The

d

attribute is built from the three calculated points:

<code>&lt;path d={`M${sx},${sy} L${mx},${my} L${ex},${ey}`} stroke={fill} strokeDasharray="1,3" fill="none" /&gt;</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

XAxis

with a series of custom bars. Gradient fills are added via a

&lt;defs&gt;

block containing a

&lt;linearGradient&gt;

definition.

<code>&lt;BarChart width={520} height={280} data={data}&gt;
  &lt;defs&gt;
    &lt;linearGradient id="gradient" x1="0" y1="0" x2="0" y2="1"&gt;
      &lt;stop offset="0%" stopColor="#00ddee" /&gt;
      &lt;stop offset="100%" stopColor="#5dc1fb" /&gt;
    &lt;/linearGradient&gt;
  &lt;/defs&gt;
  &lt;XAxis dataKey="scene" tickLine={false} axisLine={{stroke: "#5dc1fb"}} tick={{fill: "#999"}} /&gt;
  &lt;Bar dataKey="time" fill="url(#gradient)" barSize={32} shape={&lt;CustomBar /&gt;} label={&lt;CustomLabel /&gt;} /&gt;
&lt;/BarChart&gt;</code>

3.1 Implementing the Gradient

The gradient is defined inside

&lt;defs&gt;

and referenced by the

fill

attribute of the

Bar

component.

3.2 Rounded Top Corners

A custom

CustomBar

component draws a path with an arc to create a rounded top. The path uses the bar’s

x

,

y

,

width

, and

height

props.

<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 &lt;path d={d} stroke="none" fill={fill} /&gt;;
}</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

&lt;clipPath&gt;

with a deterministic

id

passed to

BarChart

, then applied to the custom path:

<code>&lt;BarChart id={uniqueId} ...&gt;
  ...
  &lt;path d={d} clipPath={`url(#${uniqueId}-clip)`} ... /&gt;
&lt;/BarChart&gt;</code>

3.4 Adding Labels

Labels are rendered with a custom

CustomLabel

component that positions a

&lt;text&gt;

element above each bar and formats the value.

<code>function CustomLabel({ x, y, width, height, value }) {
  return (
    &lt;text
      x={x + width / 2 - 1}
      y={y - 10}
      fill="#999"
      textAnchor="middle"
      className="recharts-text recharts-label"
    &gt;
      {getStudyTime(value)}
    &lt;/text&gt;
  );
}</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/

ReactSVGCustomChartsDataVisualizationRecharts
Tencent IMWeb Frontend Team
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.