Search code examples
reactjsamchartsuse-effect

Delay React Hook useLayoutEffect until useEffect is done?


I have a component in which I use the hook useEffect to retrieve data from an API. I want to display the data in a chart using AMCharts. My problem is that I need to use the hook useLayoutEffect to create the chart and the chart is based on the data retrieved with useEffect... When my chart is rendered, I don't have the data yet and my chart is empty. How can I delay the useLayoutEffect until the data is retrieved ?

I use useEffect a lot in my app to retrieve data and display the info I need. I tried to do both (retrieve data and create the chart) in the hook useEffect or in the useLayoutEffect but it does not work. I cannot use a condition before using useLayoutEffect, tried it too...

const AmChart = (props) => {
    const chartRef = useRef(null);

    const [data,setData] = useState([]);
    const [startDate,setStartDate] = useState(new Date());
    const [endDate,setEndDate] = useState(new Date());

    useEffect(() => {
        let from = startDate.getFullYear().toString() + ('0' + (startDate.getMonth() + 1)).slice(-2) + ('0' + startDate.getDate()).slice(-2);
        let to = endDate.getFullYear().toString() + ('0' + (endDate.getMonth() + 1)).slice(-2) + ('0' + endDate.getDate()).slice(-2);
        dataService.getData(from,to)
            .then(response => {
                setData(response.data);
            });
    },[]);

    useLayoutEffect(() => {
        let x = am4core.create("chartdiv", am4charts.XYChart);
        // ... creation of the chart
        chart.data = data;
        // ... creation of the chart
        chart.current = x;

        return () => {
          x.dispose();
        };
    }, []);

    return (
      <div id="chartdiv" style={{ width: "100%", height: "500px" }}></div>
    );
}

Solution

  • You should add 'data' to the list of dependencies for useEffect. For more info please read this article: Docs on useEffect conditional firing