recharts: Cannot wrap `Line` with customized component

I was trying to wrap <Line /> with my customized component. Like

const CurveLine = (props) => {
  // do some transform with props here
  return (
    <Line
      ....
    />
  )
}

but the Line didn’t render in the chart. Is there some way to do it correctly ? : )

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 16
  • Comments: 34 (4 by maintainers)

Most upvoted comments

I think this should be reopened as it still is an issue. The workaround from @cjies works but that’s certainly not how it should be. Wrapping components is a very standard thing to do in react. I believe that it should be fixed or at least it should be documented on how to do it in a proper way.

@xile611

This should be reopened since is breaking the base pattern to compose react applications @xile611

recharts sux +1

@xile611 Please, reopen this. This is a serious issue that collides with basic React approach to composition.

I found a workaround to customize original <Line> component by overwriting its default props.

import { LineChart, Line as ReLine } from 'recharts';

// Extends the Line component to overwrite its default props
class Line extends ReLine {
  static defaultProps = {
    ...ReLine.defaultProps,
    // Customized props
    strokeWidth: 2,
    dot: false,
  };
}

// In real use case
<LineChart data={data}>
  <Line dataKey="example" />
</LineChart>

If you set the statics, defaultProps, and displayName of the returned component from the HOF then you can wrap the components.

Let’s say I had a HOF that provided me a theme (from a ThemeProvider) as an example. Below is an example of wrapping the Line component:

import { Line as RCLine } from 'recharts';

const Line = ({ theme, ...props }) => {
  console.log(theme);
  return <RCLine {...props} type="monotone" dataKey="uv" stroke="#82ca9d" />;
};

const ThemedLine = withTheme(Line);

ThemedLine.defaultProps = RCLine.defaultProps;
ThemedLine.displayName = RCLine.displayName;
ThemedLine.getComposedData = RCLine.getComposedData;
ThemedLine.repeat = RCLine.repeat;
ThemedLine.renderDotItem = RCLine.renderDotItem;

I also tried this with react-redux’s connect and it works fine. Hope this helps.

@huozhi Line will render svg nodes, you can wrap it with <Surface> or <svg>.

Why is this closed? Wrapping still does not work on anything. I’ve been trying to split my graph up into its components into separate files. (Tooltip, axes, lines etc.).

@sscaff1 where does your whithTheme come from? I can’t find it anywhere.

@tibudiyanto’s solution does not work if you use hooks in the out-sourced component.

The issue still persist and @sscaff1’s workaround doesn’t work for me. I get the line with the sizes of 0x0 rendered for some reason.

This is such a react-y thing composing of components, and with this lib, you can’t just simply do const MyLine = (props) => <Line {...props} />.

This thing should be definitely mentioned in the README and at the API docs page at the very top with bold and uppercase: WE DON’T SUPPORT WRAPPING COMPONENTS.

UPD: workaround still works, but you need to pass dataKey to MyLine, and can’t hardcode it on Line;

I also want to vote for this to be reopened, we have used Recharts to build a distinct visual style for our charts but the code for each element is complex. Having to copy and paste it to new charts rather than build our own building blocks on top is bad practice and not how React is meant to be used.

const LimitArea = ({
  y1, y2, variant, label, labelPosition, fill, fillOpacity, alwaysShow,
}) => {
  console.log(variant);
  return (
    <ReferenceArea
      y1={y1}
      y2={y2}
      variant={variant}
      label={{
        position: 'right',
        value: label,
        fontSize: '1rem',
        fill: Colors.gray.hex,
      }}
      labelPosition={labelPosition}
      fill={fill}
      fillOpacity={fillOpacity}
      alwaysShow={alwaysShow}
    />
  );
};

Even just wrapping a reference area in a functional component prevents it from working. I’m aware I’m probably doing something wrong, but this is a common pattern in React and it is not documented how to use the Recharts components in this way.

Facing same issue. My ugly workaround is to create a function that returns the wrapped component with the desired props

const ReLine = props => {
  return <Line {...props} strokeWidth={2} />;
};
// and then use it like this
<LineChart width={400} height={200} data={data}>
        {ReLine({
          type: "monotone",
          label: "value",
          dataKey: "value",
          stroke: "#137752"
        })}
</LineChart>

Re-opened this (unsure why it was closed like a lot of other issues). Unfortunately, recharts items such as Line, Area, etc. rely on their parent because their parent calls the (very complex and bloated) generator function that does almost all of the logic for recharts charts. Without that function Line, etc. have basically no functionally. This is an unfortunate design flaw that hasn’t aged well as React has matured. Recharts needs a refactor of huge proportions in order to be able to support standard composition. It essentially created its own rules for what can be composed and what cannot.

recharts sux +1

Did you find a better alternative for your use case? @goneglobal