Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Line chart is not being displayed in Chart.js

The problem is quite forward, I can't see the line of the graph, and when I press any button. The time of the X-axes should change accordingly to which button is pressed I have been looking through the documentation, for quite some time, but still can't figure it out.

ChartData

import React, { useRef, useEffect, useState } from "react";
import { historyOptions } from '../chartConfig/chartConfig';
import 'chartjs-adapter-moment';
import annotationPlugin from 'chartjs-plugin-annotation';
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
Chart.register(annotationPlugin);



const determineTimeFormat = (
  timeFormat: string,
  day: any,
  week: any,
  year: any
) => {
  switch (timeFormat) {
    case "24h":
      return day;
    case "7d":
      return week;
    case "1y":
      return year;
    default:
      return day;
  }
};

interface Props {
  data: any
}

const ChartData: React.FC<Props> = ({ data }) => {
  const chartCanvasRef = useRef<HTMLCanvasElement | null>(null);
  const { day, week, year, detail } = data;
  const [timeFormat, setTimeFormat] = useState("24h");
  const [isRebuildingCanvas, setIsRebuildingCanvas] = useState(false);
  
 

  useEffect(() => {
    setIsRebuildingCanvas(true);
  }, [timeFormat]);

  useEffect(() => {
    if (isRebuildingCanvas) {
      setIsRebuildingCanvas(false);
    }
  }, [isRebuildingCanvas]);

  useEffect(() => {
      if (chartCanvasRef && chartCanvasRef.current && detail) {
    const chartCanvas = chartCanvasRef.current
    if (isRebuildingCanvas || !chartCanvas) {
      return;
    }
  
    const chartInstance = new Chart(chartCanvasRef.current, {
      type: "line",
      data: {
        datasets: [
          {
            label: `${detail.name} price`,
            data: determineTimeFormat(timeFormat, day, week, year),
            backgroundColor: "rgba(134,159,152, 1)",
            borderColor: "rgba(174, 305, 194, 0.4",

          },
        ],
      },

Options

  options: {     
        plugins: {
          annotation: {
            annotations: {
           
            }
          }
        },
      
        animations: {
          tension: {
            duration: 1000,
            easing: 'linear',
            from: 1,
            to: 0,
            loop: true
          }
        },
        maintainAspectRatio: false,
        responsive: true,
        scales: {
          x: 
            {         
              type: 'time',
            },  
        },
      }
    });
    return () => {
      chartInstance.destroy();
    }
  }}, [day, isRebuildingCanvas,timeFormat, week, year, detail]);

Rest of the Component code


return (
    <div className='chart__container'>
    {renderPrice()}
      {isRebuildingCanvas ? undefined : (
        <canvas ref={chartCanvasRef} id='myChart' width={250} height={250}></canvas>
      )}
      <button className='time__format' onClick={() => setTimeFormat("24h")}>24h</button>
      <button className='time__format' onClick={() => setTimeFormat("7d")}>7d</button>
      <button className='time__format'  onClick={() => setTimeFormat("1y")}>1y</button>
    </div>
  );
};

export default ChartData;
like image 535
mura1 Avatar asked Nov 06 '22 01:11

mura1


1 Answers

Looks like your isRebuildingCanvas logic might be inconsistent, or I don't just understand it.

Anyway, from the Chart.js perspective, you'd want to change the data and call chartInstance.update() when pressing the button that changes the data.

Partial example:

  const canvas = useRef(null);
  const [chart, setChart] = useState();
  const [timeFormat, setTimeFormat] = useState("24h");

  useEffect(() => {
    if (chart || !canvas.current) return;
    const ctx = canvas.current.getContext("2d");
    if (!ctx) return;

    const config = {/*...*/};

    setChart(new Chart(ctx, config));
  }, [chart, canvas]);

  useEffect(() => {
    if (!chart) return;

    chart.config.data.datasets[0].data = determineTimeFormat(timeFormat, day, week, year);
    chart.update();
  }, [chart, timeFormat]);

And a complete, very similar example: https://codesandbox.io/s/blissful-faraday-hzcq0

like image 54
kurkle Avatar answered Nov 11 '22 04:11

kurkle