Exploring Recharts: what can be rendered inside a Recharts container?
The top level charts in Recharts act as a container for other elements which can be rendered inside it. Some examples are
BarChart. These charts act as top level containers for other elements like
Unlike many other charting libraries which allow all of this configuration and customizations by passing props or parameters to the top level container (which then takes care of rendering everything), Recharts allows you to have full control on what should be rendered inside the container and allows each of the children to be customized separately, while also making sure that each of these children get the required context from the parent.
As an example, consider this example taken from another good charting library Nivo:
and now consider a similar example in Recharts:
It is a lot easier on the eyes and it allows to customize each child element separately, so you can pass props to
YAxis, etc, as you would pass to any React components. Also note that the
Linechart would implicitly pass on the required data to
Tooltip, i.e, what is the y-value and x-value of the point being hovered over, while also allowing the developer to customize other things in Tooltip through explicit props. .
This very much aligns with how React components are composed. Of course, even when allowing this kind of flexibility, Recharts still has to make sure that only appropriate elements are rendered within appropriate parents, for example, you shouldn’t expect to be able to render a
Line inside a
PieChart, and correctly so, Recharts explicitly disallows this.
How does rechart disallow certain elements?
Recharts checks the type of the element being rendered, and if does not match the allowed types, it would just simply ignore that element. It does not show an error or warning and excludes that element from the rendered output.
In the above codesandbox, Recharts does not render the
div element at all.
In some ways this is good, because accidentally rendering a wrong component does not break the UI, but it is also not the best developer experience as you do not get any warnings on the console even in developer mode, when you try to render an inappropriate component.
So, what can you render inside a top level container ?
- Recharts provided components
- svg elements
- DOM elements
- Custom Components (?)
Recharts provided components:
As seen in our example above and as mentioned in the Recharts documentation, every top level container (or rather, every Recharts component) can only render certain Recharts provided components. For example,
LineChart can render
yAxis, and so on, but not a
The top level chart containers render an
svg element internally and allow any elements to be rendered inside the
svg as per the svg spec. So, you can render
g, and a lot of other svg elements directly inside the top level container. This allows for some level of customization, but there are some drawbacks. Recharts doesn’t/can’t pass any context to these svg elements, so let’s say you want to render a
circle inside the chart at a particular x-value from your data, then you would have to explicitly do the scale calculations and figure out the
cy of this circle in cartesian coordinates (this is difficult as Recharts does not directly expose the
yAxis scales, so that you can map the data coordinates to cartesian coordinates), instead you can just use the
ReferenceDot component provided by Recharts, pass on the x-value from the data and Recharts would take care of rendering the
circle in the appropriate transformed coordinates in the cartesian coordinate system.
Also, not all Recharts components allow all the appropriate svg elements, for example, although a
ReferenceDot renders a circle, and in svg, a
circle can have an
animate element, if you try to pass
animate as a child to
ReferenceDot, it would be ignored.
But you can at least rely on this functionality at the top level container.
This capability is not specifically provided by Recharts, rather, the svg specs allow this. As we discussed above, Recharts allows rendering Recharts provided components inside the top level container, we also saw that the top level container is an
svg and so we can render svg elements directly inside it, like
rect, etc. But, manipulating svg elements is sometimes much more difficult than manipulating regular DOM elements, for e.g, centering text in svg using the
text element is much more difficult than centering text in a
div. So, for such usages, svg specs allow rendering HTML elements inside svg using a
Unfortunately, Recharts would simply ignore any DOM elements that we try to directly render inside the chart container, but as we have seen above, we can enable this using a
foreignObject. Also, as a side note, although most of the Recharts components only allow svg elements to be used in customization , like when customizing label, or using the
Tooltip is one component that allows customization using HTML . This is possible because the
Tooltip is actually rendered by Recharts outside the
svg and so it does not have the same limitations as the other Recharts components.
So what about custom components ?
Can we create a new React component which returns an svg element and render it inside the top level chart container ? No.
Can we create a new React component which returns a foreignObject element and render it inside the top level chart container ? No.
Can we create a new react component which returns a Recharts component and render it inside the top level chart container ? Sadly, No.
As discussed above, Recharts explicitly checks for the type of element/component being rendered and ignores if the type does not match any allowed types, so although your React component returns the appropriate Recharts component, the type of the React component (or the class/constructor function, for simplicity), is something that Recharts does not have in its “allow” list and hence it ignores it completely.
So, if you can’t provide Custom components, how do you customize things in Recharts? Well, for all the components that allow customization, Recharts exposes this capability through props.
For components which support labels, you can pass in a function which renders a custom label.
Tooltip, you can pass in a function/React component in the
content prop which renders a custom Tooltip.
ReferenceDot, you can pass in a function in the
shape prop. This function can return any svg element which should be rendered as the
For all these examples, Recharts passes on the required context to this function/React component and you can use this information to render anything you want.
A list of all other posts in this series:
- Exploring Recharts: Reference Area
- Exploring Recharts: multiple ReferenceLine segments
- Exploring Recharts: using foreignObject to render custom HTML
- Exploring Recharts: What can be rendered inside a Recharts contianer ?
- Exploring Recharts: different ways of accessing data
- Exploring Recharts: Pulsating circle using ReferenceDot
- Exploring Recharts: LineChart with different colored segments for a single Line