Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use this sunburst in React? #85

Closed
matter13311 opened this issue Jun 2, 2022 · 7 comments
Closed

How to use this sunburst in React? #85

matter13311 opened this issue Jun 2, 2022 · 7 comments

Comments

@matter13311
Copy link

matter13311 commented Jun 2, 2022

How do I use this npm package with React?
`
import React from 'react'
import Sunburst from 'sunburst-chart';

return(
< Sunburst/ >
)
`

I get an error saying Sunburst can't be used in JSX.

@vasturiano
Copy link
Owner

@matter13311 this is not a React component, thus you cannot use it directly in a React environment directly.
The manner to instantiate this module is specified in the docs, so you'll need to write a React wrapper around it if you want to use it in a JSX context.

react-kapsule offers a means to do that easily, but there are other ways you can achieve the same.

@hallundbaek
Copy link

Could you give an example with react-kapsule?

@vasturiano
Copy link
Owner

Something along these lines:

import fromKapsule from 'react-kapsule';
import sunburstKapsule from 'sunburst-chart';

const Sunburst = fromKapsule(sunburstKapsule);

then use it in React:

<Sunburst data={myData} />

@hallundbaek
Copy link

Thanks for the fast reply!

Your example was also my intuition but trying it out in yields the following typeerror:

Argument of type '(configOptions?: ConfigOptions | undefined) => SunburstChartInstance' is not assignable to parameter of type 'KapsuleClosure'.
Property 'resetProps' is missing in type 'SunburstChartGenericInstance<SunburstChartInstance>' but required in type 'KapsuleInstance'.ts(2345)

@vinicius-gregorio
Copy link

did you figured it out?

@hallundbaek
Copy link

hallundbaek commented Sep 8, 2022

No, I ended up not using react-kapsule. Just generated the chart and applied it to a div with an id, something to this effect:

import sunburst from "sunburst-chart";

export type SunburstLeaf = {
  name: string;
  size: number;
  color: string;
};

export type SunburstNode = {
  name: string;
  color: string;
  size: number; 
  children: (SunburstNode | SunburstLeaf)[];
};

interface SunburstElementProps {
  data: SunburstNode | undefined
}

export const SunburstElement = (props: SunburstElementProps) => {
  const { data } = props;
  
  useEffect(() => {
    if (data) {
      sunburst()
        .data(data)
        .label("name")
        .size("size")
        .height(200)
        .width(200)
        .color("color")(document.getElementById("chart")!);
    }
  }, [data]);
  
  return <div id="chart" />
}

And some extra logic to delete the children of the div when data changes.

@coreymunn3
Copy link

coreymunn3 commented Jun 5, 2024

I ended up with an implementation similar to above, but was still getting the chart duplication error.

As @hallundbaek hints here,

And some extra logic to delete the children of the div when data changes.

we need to provide a cleanup function to the useEffect. This StackOverflow says exactly what to do, and I found it to be correct.

Here's my final useEffect implementation. I used explicit props coming from the parent component and passed them to the chart.

useEffect(() => {
    if (treeData) {
      sunburstChart
        .data(treeData)
        .width(width || chartRef.current.offsetWidth)
        .height(height || chartRef.current.offsetWidth) // makes it square if no height provided
        .label(getLabel)
        .size(getSize)
        .color(getColor)
        .strokeColor(getStrokeColor)
        .nodeClassName(getNodeClassName)
        .minSliceAngle(minSliceAngle)
        .maxLevels(maxLevels)
        .excludeRoot(excludeRoot)
        .centerRadius(centerRadius)
        .radiusScaleExponent(radiusScaleExponent)
        .sort(getSortOrder)
        .showLabels(showLabels)
        .labelOrientation(labelOrientation)
        .handleNonFittingLabel(handleNonFittingLabel)
        .showTooltip(getShowTooltip)
        .tooltipTitle(getTooltipTitle)
        .tooltipContent(getTooltipContent)
        .onHover(onHover)
        .onClick(onClick)
        .transitionDuration(transitionDuration)(
        document.getElementById('sunburst')
      );
    }
    return () => {
      if (chartRef.current?.children[0]) {
        chartRef.current.removeChild(chartRef.current.children[0]);
      }
    };
  }, [treeData]);

where the component returns

return <div id='sunburst' className={classes.root} ref={chartRef} />;

@vasturiano I think we can mark this issue as closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants