Search code examples
javascriptreactjschart.jsreact-chartjs

Using Chart.js in functional React component, not allowing me to toggle data: "properties undefined"


I'm trying to make dynamic data in a Chart.js chart, but how do I make the chart const available to a toggle function?

The chart displays fine, but then I can't update it at all. I believe this is due to scoping. How do I return the Chart.js objects to the main function?

The code:

import React, { useContext, useEffect, useState } from "react";
import "./questions_trends.css";
import axios from 'axios';
import ReactTooltip from 'react-tooltip';

import { Chart } from "chart.js";

function Trends(){

    const user_context = useContext(UserContext)
    const [positiveChart, setPositiveChart] = React.useState(undefined);

    function makeChart(data){

        // Create the trends chart
        // positive_trend = 
        setPositiveChart = new Chart('positiveChart', {
            type: 'bar',
            data: { 
                labels: data.positive,
                datasets: [
                {
                    label: 'Team Positive',
                    data: data.team_positive,
                    backgroundColor: data.color
                },
                {
                    label: 'You Positive',
                    data: data.positive,
                    backgroundColor: data.color
                }]
            },
            options: {
            }
        }); 
    }

    function toggle(value) {
        if(positiveChart.isDatasetVisible(value)){
            positiveChart.hide(value)
        }

        if(!positiveChart.isDatasetVisible(value)){
            positiveChart.show(value)
        }
    }

    useEffect( async () => {
        let result = await axios.get("/api/monthly_tones")
            makeChart(result.data)
    }, []);


    useEffect( async () => {
        return positiveChart.destroy()
    }, []);

    //Render to Dom
    
    return (                    
        <div className="question_positivity_container">
            <canvas id="positiveChart" width="auto" height="70vh"></canvas>

            <button onClick={() => toggle(0)}>See All Cratic</button>
        </div>
    );
};

export default Trends;

The toggle and the useEffect functions don't work: TypeError: Cannot read properties of undefined (reading 'isDatasetVisible')

I think this is because the positiveChart and engagedChart are not in their scope. How do I solve this??

Any help appreciated.

--- Update

The solution required using a const chart = new Chart({}) inside the makeChart() function, and then pushing chart into state like this: setPositiveChart(chart).

That updated the function state and made the variable available everywhere.

I accepted the answer below because it was the right approach and got me to the answer. Thanks for the help!


Solution

  • Your problem is that positiveChart is not in the scope of your other functions because you declare it inside makeChart. In order to fix that you must have it in the react useState like this:

    const [positiveChart, setPositiveChart] = React.useState(undefined);
    

    and then inside makeChart you can use setPositiveChart in order to create it. Afterwards you will be able to access it correctly in your useEffect functions.

    You can read more about it in the React docs about state hooks.