Search code examples
javascriptreactjsamcharts4

React amchart4 rendering only watermark logo?


I am trying to create a pie chart, to display data. When I edit the file and save to see the result, the pie chart suddenly loads onscreen(displaying the data correctly). If I refresh the page though, I only have the logo on screen loaded, no pie. Can anyone point me to what I am doing wrong?

Component:

import React, { useLayoutEffect, useRef } from "react";
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";

import am4themes_animated from "@amcharts/amcharts4/themes/animated";
am4core.useTheme(am4themes_animated);

const Pie = (props) => {
  const chart = useRef(null);

  useLayoutEffect(() => {
    let pie = am4core.create("chartdiv", am4charts.PieChart3D);

    let pieData = [];
    props.data.map((item) => {
      let obj = {};
      obj = { name: item.prod_name, quantity: item.prod_quantity };
      pieData.push(obj);
    });
    // ...
    pie.data = pieData;
    let pieSeries = pie.series.push(new am4charts.PieSeries3D());
    pieSeries.slices.template.strokeOpacity = 1;
    pie.radius = am4core.percent(70);
    
    pieSeries.dataFields.value = "quantity";
    pieSeries.dataFields.category = "name";
    pieSeries.hiddenState.properties.opacity = 1;
    pieSeries.hiddenState.properties.endAngle = -90;
    pieSeries.hiddenState.properties.startAngle = -90;
    pie.hiddenState.properties.radius = am4core.percent(60);
    pie.innerRadius = am4core.percent(40);
    chart.current = pie;
    return () => {
      pie.dispose();
    };
  }, []);
  return <div id="chartdiv" className="pie"></div>;
};

export default Pie;

Update: Component Statistics:

import Pie from "./Charts/Pie";

const Statistics = () => {

  const [data, setData] = useState([]);
  useEffect(() => {
    axios
      .get("http://localhost:3001/statistics")
      .then((res) => setData(res.data.data.orders));
  }, []);

  return (
    <section className="statistics">
      <Pie data={data} />
    </section>
  );
};

export default Statistics;

Also, the css for the className='pie' :

.pie {
  height: 500px;
}

Solution

  • So since you are using useEffect with empty dependency array, your component Pie will only run the pie chart creation code inside useEffect on component mount.

    Now since you are fetching the data using axios asynchronously, the data will be passed to the Pie component after it is already mounted. So now data changes will not be reflected in Pie chart.

    adding the props.data in the dependency array will run the useEffect whenever new data is passed to the Pie component. (i.e. on props update).

    useEffect(() => {
      // your code for rendering pie chart
      return () => {
        pie.dispose();
      };
    }, [props.data])
    

    https://codesandbox.io/s/blissful-fast-djuxm?file=/src/Pie.jsx