4

I'm reading the docs on flexible charts and trying to apply them to a pie chart:

import React from 'react'
import { RadialChart, FlexibleXYPlot } from 'react-vis'

const MyChart = ({data}) => (
  <div>
    <FlexibleXYPlot>
      <RadialChart
        data={data}
        colorType="literal"
      />
    </FlexibleXYPlot>
  </div>
)

But when rendering this, I get markup like this:

<div>
  <div style="width: 100%; height: 100%;">
    <div class="rv-xy-plot " style="width: 0px; height: 0px;">
    </div>
  </div>
</div>

As you can see, the dimensions of the rv-xy-plot element are explicitly set to 0px. What am I doing wrong? How do I create a responsive pie chart?

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402
  • 1
    I'm having the same issue. Did you ever figure out what the problem was? – rottweiler Mar 21 '19 at 05:39
  • 1
    @rottweiler: No, I didn't. I can't even remember what I did instead, but I think I ended up going with a different component. The end result is up at https://bildaregering.nu, so if there's something useful you can look at the code there (or at https://github.com/tomasaschan/bildaregering.nu) – Tomas Aschan Mar 22 '19 at 09:43

5 Answers5

7

I was recently running into the same problem with a lot of the charts from this package. A work around I found is to use React-virtualized-auto-sizer. Essentially what it does is wrap components that require a width and height around it, then pass the width and height of the parent container (that the auto sizer is in). Here is an example:

<div style={{height:'100%',width:'100%'}} className={"mb-4"}>
<AutoSizer>
    {({ height, width }) => (
        <RadialChart
            data={this.state.myData}
            width={width}
            height={height}
            onValueMouseOver={this.handleMouseOver}
            className={"mb-4"}
            labelsAboveChildren={true}
        />
    )}
</AutoSizer>

So the autosizer is looking above it at the outer div, figuring out the height and width, then passing it to the chart.

Shay Erlichmen
  • 31,691
  • 7
  • 68
  • 87
Ianohurr
  • 129
  • 3
  • 10
3

I can help with this, I had exactly the same problem with a Sankey chart; the documentation makes it look like the FlexibleXYPlot will make any chart responsive but that's not the case.

The correct approach is hinted at at the bottom of this page - https://uber.github.io/react-vis/documentation/api-reference/flexible-plots

So for a RadialChart you need to do this:

import { RadialChart, makeVisFlexible} from "react-vis";

const FlexRadialChart=makeVisFlexible(RadialChart)

and then use the new component that you just created with the responsive code baked in:

      <FlexRadialChart
        data={data}
        colorType="literal"
      />
Davie
  • 162
  • 9
  • I was struggling with this because the parent containers height was only defined by min-height. To make this work to need to explicitly define height (e.g. 70vh) – Chaoste May 17 '19 at 06:59
  • I'm glad my answer pointed you in the right direction - it would also have answered the original question – Davie Jun 14 '19 at 09:24
1

It does not seem like the library support wrapping radial chart with FlexibleXYPlot or XYPlot for that matter (see issue Responsive RadialChart "react-vis": "^1.7.7", never solved, and I couldn't get it to work), ontop of that RadialChart chart requires the width and height to be sat. enter image description here

Now based on the following issues FlexibleXYPlot requires height props a pr was made to fix this issue but never merged. Based on Alex Sandiiarov implementation, the following code can be used to make the pie chart responsive:

import React, { Component } from 'react';
import ResizeObserver from 'resize-observer-polyfill';
import { RadialChart } from 'react-vis';

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            height: 0,
            width: 0
        };
    }
    componentDidMount() {
    //When mounted set our start size
    this.setSize();
    //Lets observe changes with resize-observer-polyfill
    this.observer = new ResizeObserver(entries => this.setSize());
    //Lets observe our node
        this.observer.observe(this.node);
    }

    componentWillUnmount() {
        this.observer.disconnect();
    }

    setSize = () => {
        const { height, width } = this.node.getBoundingClientRect();
        this.setState({ height, width });
  };

    render() {
        const { height, width } = this.state;
        return (
            <div
                ref={node => {
                    if (node) {
                        this.node = node;
                    }
                }}
                style={{ width: '100vw', height: '100vh' }}
            >
                <RadialChart
                    className={'donut-chart-example'}
                    getAngle={d => d.theta}
                    data={[
                        { theta: 2, className: 'custom-class' },
                        { theta: 6 },
                        { theta: 2 },
                        { theta: 3 },
                        { theta: 1 }
                    ]}
                    width={width}
                    height={height}
                    padAngle={0.04}
        colorType="literal"
                />
            </div>
        );
    }
}

export default App;

Hope this helps you or points you in a useful direction :)

jonaslagoni
  • 663
  • 7
  • 23
1

I just add display: flex on parent div and flex: 1 on child div try this, i hope it'll help you out. Thanks

<div>
  <div style="display: flex; width: 100%; height: 100%;">
    <div class="rv-xy-plot" style="flex: 1">
    </div>
  </div>
</div>
Hassan Siddiqui
  • 2,799
  • 1
  • 13
  • 22
0

I was able to do it with react hooks, take a look at it:

https://codesandbox.io/s/responsive-pie-chart-react-vis-ogor6

If you maybe need it to resize within an element (a <div> for example) you might want to use an useRef to reference the width/height of the desired element

Fabian Merchan
  • 943
  • 8
  • 15