skip to Main Content

I wrote a BarChart in react. Code is given below.
BarChart.tsx

import "chartjs-plugin-datalabels";
import { HorizontalBar } from "react-chartjs-2";
import styled from "styled-components";
import { BRAND } from "../util/constants";
import schema, { colours } from "../util/theme/schema";
import {DivProps} from "../components/styled/common.styled.type"
import { ICharDataSet, IDataSet, IDeafualtProps } from "./barChart-type";


const defaultProps: IDeafualtProps = {
  displayTitle: true,
  displayLegend: false,
  legendPosition: "left",
  ticks: false,
  stacked: false,
  xAxisDisplay: true,
  yAxisDisplay: true,
  BC_Title_Text: "",
  BC_Label: "",
  BC_X_Axis_Label: "",
  barPercentage: 0,
  tooltips: false,
  width: "480px",
  height: "303px",
  left: "18px",
  bottom: "64px",
  fontFamily: "'RNHouseSans','Arial',sans-serif",
  fontSize: 13,
  fontColor: "#808191",
  fontWeight: 400,
  maintainAspectRatio: true,
  responsive: true,
  borderWidth: 0,
  dataLabelsDisplay: false,
  datalabelsColor: `${colours[BRAND]["zb-white"]}`,
  datalabelsTextAlign: "center",
  displayColors: false,
  xAxisGridLinesdisplay: false,
  xAxisGridLinesDrawBorder: false,
  xAxisGridLinesDrawOnChartArea: false,
  xAxisGridLinesDrawTicks: false,
};

const BarChart = (props: any) => {
  props = { ...defaultProps, ...props };

  const MONTHS = props.MONTHS;
  const ChartData = props.ChartData;
  const Color = props.Color;
  const borderWidth = props.borderWidth;
  const dataSets:IDataSet[] = props.stacked
    ? [
        {
          label: props.BC_Label,
          data: [...ChartData],
          backgroundColor: [...Color],
          borderWidth: borderWidth,
        },
        {
          label: "stacked",
          data: [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
          backgroundColor: props.stackedColor,
          borderWidth: borderWidth,
        },
      ]
    : [
        {
          label: props.BC_Label,
          data: [...ChartData],
          backgroundColor: [...Color],
          borderWidth: borderWidth,
        },
      ];

  const chartData: ICharDataSet = {
    labels: [...MONTHS],
    datasets: dataSets,
  };

  return (
    <BarchartContainer 
      width={`${props.width}`}
      height={`${props.height}`}
      top={`${props.top}`}
      right={`${props.right}`}
      flex={`${props.flex}`}
      data-testid="bar-chart"
    >
      <HorizontalBar
        data={chartData}
        options={{
          responsive: props.responsive,
          maintainAspectRatio: props.maintainAspectRatio,
          width: !props.maintainAspectRatio ? props.width : "auto",
          height: !props.maintainAspectRatio ? props.height : "auto",
          tooltips: {
            displayColors: props.displayColors,
            filter: function (tooltipItem: any) {
              if (props.tooltips) return props.filterTooltip(tooltipItem);
            },
            custom: function (tooltipModel :any) {
              if (!props.tooltips) tooltipModel.opacity = 0;
            },
            callbacks: props.tooltips
              ? {
                  title: function (tooltipItem :any) {
                    return props.customiseTooltipTitle(tooltipItem);
                  },
                  label: function (tooltipItem :any) {
                    return props.customiseTooltipLabel(tooltipItem);
                  },
                }
              : {},
            titleAlign: "center",
            titleFontSize: 12,
            titleFontFamily: props.fontFamily,
            titleFontStyle: "normal",
            bodyAlign: "center",
            bodyFontSize: 14,
            bodyFontFamily: props.fontFamily,
            bodyFontStyle: "bold",
          },
          scales: {
            xAxes: [
              {
                gridLines: {
                  display: props.xAxisGridLinesdisplay,
                  color: props.fontColor,
                  drawBorder: props.xAxisGridLinesDrawBorder,
                  drawOnChartArea: props.xAxisGridLinesDrawOnChartArea,
                  drawTicks: props.xAxisGridLinesDrawTicks,
                },
                display: props.xAxisDisplay,
                barPercentage: props.barPercentage,
                ticks: {
                  fontFamily: props.fontFamily,
                  fontSize: props.fontSize,
                  fontColor: props.fontColor,
                  fontStyle: props.fontWeight,
                  lineHeight: props.xAxisTicksLineHeight,
                },
              },
            ],
            yAxes: [
              {
                gridLines: {
                  display: false,
                },
                stacked: props.stacked,
                ticks: props.ticks
                  ? {
                      beginAtZero: props.beginAtZero,
                      min: props.min,
                      max: props.max,
                      stepSize: props.stepSize,
                      display: props.yAxisDisplay,
                      fontFamily: props.fontFamily,
                      fontSize: props.fontSize,
                      fontColor: props.fontColor,
                      fontStyle: props.fontWeight,
                    }
                  : {
                      display: props.yAxisDisplay,
                      fontFamily: props.fontFamily,
                      fontSize: props.fontSize,
                      fontColor: props.fontColor,
                      fontStyle: props.fontWeight,
                    },
              },
            ],
          },
          layout: {
            padding: {
              bottom: -20,
            },
          },
          title: {
            display: props.displayTitle,
            text: props.BC_Title_Text,
            fontSize: 14,
            fontStyle: 700,
            fontColor: "#424B5A",
            position: "left",
          },
          legend: {
            display: props.displayLegend,
            position: props.legendPosition,
            labels: {
              fontSize: 14,
              fontStyle: 700,
              fontColor: "#424B5A",
              boxWidth: 0,
            },
          },
          elements: {
            rectangle: {
              borderSkipped: "none",
            },
          },
          plugins: {
            datalabels: {
              display: props.dataLabelsDisplay,
              color: props.datalabelsColor,
              align: "left",
              textAlign: props.datalabelsTextAlign,
              font: {
                size: "14",
                weight: "700",
                family: props.fontFamily,
                lineHeight: "1.3",
              },
              formatter: function (value: any, context: any) {
                return props.customiseDataLabel(value, context);
              },
            },
          },
        }}
      />
      <X_Axis_Label_Container left={`${props.left}`} bottom={`${props.bottom}`}>
        <X_Axis_Label>{props.BC_X_Axis_Label}</X_Axis_Label>
      </X_Axis_Label_Container>
    </BarchartContainer>
  );
};

const BarchartContainer = styled.div <DivProps>`
  position: relative;
  width: ${(props) => props.width || "100%"};
  height: ${(props) => props.height || "100%"};
  color: ${schema[BRAND].colors.loginPage.pageSubtitleColor};
  top: ${(props) => props.top || "auto"};
  right: ${(props) => props.right || "auto"};
  flex: ${(props) => props.flex || "auto"};
`;
const X_Axis_Label_Container = styled.div<DivProps>`
  position: absolute;
  left: ${(props) => props.left || "auto"};
  bottom: ${(props) => props.bottom || "auto"};
  color: ${schema[BRAND].colors.pageTitle};
`;

const X_Axis_Label = styled.h3`
  font-size: 13px;
  // color: #808191;
  font-weight: 400;
  line-height: 18px !important;
`;

export default BarChart;  

BarChart.test.tsx

import { render } from "../util/test-utils";
import BarChart from "./BarChart";

describe("barchart test", () => {
    it("should show barchart", () => {
        const { getByTestId } = render(<BarChart />);
        const barchart = getByTestId("bar-chart");
        expect(barchart).toBeInTheDocument();
    })
})  

When I run the test code, I get undefined error.

TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))

      67 |         {
      68 |           label: props.BC_Label,
    > 69 |           data: [...ChartData],
         |               ^
      70 |           backgroundColor: [...Color],
      71 |           borderWidth: borderWidth,
      72 |         },  

What am I missing? How can I fix it?

2

Answers


  1. The error you get is correct. You can not do this with undefined values: data: [...ChartData]. The Spread operator throws the error you described.

    const ChartData = props.ChartData; – this is undefined

    props.CharData is undefined because you do not pass it as prop render(<BarChart />) and it is not initialized in the default props as well

    Login or Signup to reply.
  2. In your BarChart component you have not defined ChartData in your defaultProps. I am assuming your IDeafualtProps interface does not have ChartData property or defined as optional/undefined. I would suggest adding ChartData as an empty array in defaultProps.

    // Assuming IDeafualtProps has ChartData property.
    const defaultProps: IDeafualtProps = {
       // ...other properties
       ChartData: []
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search