Tiger_Stripes
Tiger_Stripes

Reputation: 525

Destroying Chart js within useEffect - React

I am having trouble destroying the previous chart when the a new chart is created.

The issue is that if if(myChart) myChart.destroy() never fires. Perhaps this is because the myChart variable only exists within the useEffect.

While the myChart variable could be allocated to a state, you wouldn't be able to call destroy() on a state directly.

So how would you go about this?

The below example renders a pie or a bar chart depending on the value of graphType:

import React, { useEffect } from "react";
import Chart from "chart.js";

export default function GraphMaker({ graphType }) {
    useEffect(() => {
        const ctx = document.getElementById("myChart");

        if (myChart) myChart.destroy()

        if (graphType === "pie") {
            console.log(myChart)

            var myChart = new Chart(ctx, {
                type: "pie",
                data: {
                    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
                    datasets: [
                        {
                            label: "# of Votes",
                            data: [12, 19, 3, 5, 2, 3],
                            backgroundColor: [
                                "Red",
                                "Blue",
                                "Yellow",
                                "Green",
                                "Purple",
                                "Orange"
                            ],
                            borderColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
                            borderWidth: 1
                        }
                    ]
                }
            });
        } 
        else if (graphType === "bar") {
            var myChart = new Chart(ctx, {
                type: "bar",
                data: {
                    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
                    datasets: [
                        {
                            label: "# of Votes",
                            data: [12, 19, 3, 5, 2, 3],
                            backgroundColor: [
                                "Red",
                                "Blue",
                                "Yellow",
                                "Green",
                                "Purple",
                                "Orange"
                            ],
                            borderColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
                            borderWidth: 1
                        }
                    ]
                }
            });
        }
    }, [graphType])

    return (
        <>
            <canvas id="myChart" />
        </>
    );
}

Upvotes: 0

Views: 1488

Answers (1)

LeeLenalee
LeeLenalee

Reputation: 31421

In the new docs they also use this, they solved it by destroying the chart in the return of the use effect like this:

useEffect(() => {
    const cfg = {
      type: 'doughnut',
      data: {
        labels: [
          'Red',
          'Blue',
          'Yellow'
        ],
        datasets: [{
          label: 'My First Dataset',
          data: [300, 50, 100],
          backgroundColor: [
            'rgb(255, 99, 132)',
            'rgb(54, 162, 235)',
            'rgb(255, 205, 86)'
          ],
          hoverOffset: 4
        }]
      }
    };
    const chart = new Chart(canvas.current.getContext('2d'), cfg);
    return () => chart.destroy();
  });

Link to their doc with live example: https://www.chartjs.org/docs/master/charts/doughnut/

Upvotes: 1

Related Questions