xanderdeseyn / react-native-responsive-linechart

A customizable and responsive line or area chart for react-native
https://react-native-responsive-linechart.surge.sh
MIT License
202 stars 46 forks source link

Crashing issue when all y-values are zero #128

Open lindan4 opened 2 years ago

lindan4 commented 2 years ago

I am using this library to generate a graph to plot health history.

I have a method which generates points (x-coordinates and y-coordinates)

const renderGraphDataMonthly = (graphData) => {
  const numDaysInMonth =  moment().daysInMonth()

  let monthData = new Array(numDaysInMonth).fill(0)
  let monthCount = new Array(numDaysInMonth).fill(0)

  let beginFilt = moment().startOf('month')
  let endFilt = moment().endOf('month')

  let filteredGraphData = graphData.filter(item => {
    return (beginFilt.unix() <= item.date) && (item.date <= endFilt.unix())
  })

  for (let data of filteredGraphData) {
    let dateOfLog = moment.unix(data.date).date() - 1
    let parsedValue = parseInt(data.value)
    monthData[dateOfLog] += parsedValue
    monthCount[dateOfLog] += 1
  }

  let newGraphData = monthData.map((item, index) => {
    return {
      x: index,
      y: (monthCount[index] !== 0) ? (item / monthCount[index]) : 0
    }
  })

  return newGraphData

}

Assuming that there are no entries for a month, all points should be {x: n, y: 0) where 0 <= n < number of days in month.

The chart element is rendered as follows.

<Chart
              style={{
                height: 220,
                width: "100%",
                backgroundColor: "white",
                borderRadius: 15,
                // opacity: 0.8,
              }}
              data={this.state.selectedData[this.state.selectedIndex]}
              padding={{ left: 35, bottom: 35, right: 25, top: 25 }}
              xDomain={{
                min: this.getMinX(this.state.selectedData[this.state.selectedIndex]),
                max: this.getMaxX(this.state.selectedData[this.state.selectedIndex])
              }}
              yDomain={{
                min: this.getMinY(this.state.selectedData[this.state.selectedIndex]),
                max: this.getMaxY(this.state.selectedData[this.state.selectedIndex]),
              }}
              viewport={{
                initialOrigin:
                  this.state.selectedIndex === 3
                    ? { x: 0 }
                    : this.state.selectedIndex === 2
                    ? { x: 0 }
                    : this.state.selectedIndex === 1
                    ? { x: 0 }
                    : this.state.selectedIndex === 0
                    ? { x: 0 }
                    : null,
                size: {
                  width:
                    this.state.selectedIndex === 3
                      ? 8
                      : this.state.selectedIndex === 2
                      ? 10
                      : this.state.selectedIndex === 1
                      ? 6
                      : this.state.selectedIndex === 0
                      ? 6
                      : null,
                },
              }}
              disableGestures={this.state.selectedIndex === 1 ? true : false}
            >
              <VerticalAxis
                tickCount={5}
                includeOriginTick={false}
                theme={{
                  axis: { visible: false },
                  ticks: { visible: false },
                  labels: {
                    label: {
                      rotation: 0,
                      color: "black",
                      fontSize: 12,
                      fontWeight: 300,
                      textAnchor: "end",
                      dx: -10,
                      dy: 4,
                    },
                    // formatter: (v) => v.toFixed(0),
                    formatter: (v) => numeral(v).format("0a"),
                  },
                  grid: {
                    stroke: {
                      color: "grey",
                      width: 0.3,
                      opacity: 0.5,
                      dashArray: [5],
                    },
                  },
                }}
              />

              <HorizontalAxis
                tickCount={
                  this.state.selectedIndex === 3
                    ? 12
                    : this.state.selectedIndex === 2
                    ? moment().daysInMonth()
                    : this.state.selectedIndex === 1
                    ? 7
                    : this.state.selectedIndex === 0
                    ? 24
                    : null
                }
                includeOriginTick
                theme={{
                  axis: { visible: false },
                  ticks: { visible: false },
                  labels: {
                    label: {
                      rotation: 0,
                      color: "black",
                      fontSize: 12,
                      fontWeight: 300,
                      textAnchor: "middle",
                      dx: 0,
                      dy: -20,
                    },
                    formatter: (xValue) =>
                      this.state.selectedIndex === 3
                        ? moment().month(xValue).format("MMM").toUpperCase() // Y
                        : this.state.selectedIndex === 2
                        ? xValue + 1 // M
                        : this.state.selectedIndex === 1
                        ? moment().day(xValue).format("ddd") // W
                        : this.state.selectedIndex === 0
                        ? moment().hour(xValue).format("h A")
                        : null, // M
                  },
                  grid: {
                    stroke: {
                      color: "grey",
                      width: 0.3,
                      opacity: 0.5,
                      dashArray: [5],
                    },
                  },
                }}
              />
              <Line
                initialTooltipIndex={
                  this.state.selectedIndex === 3
                    ? moment().month()
                    : this.state.selectedIndex === 2
                    ? moment().date()
                    : this.state.selectedIndex === 1
                    ? moment().day()
                    : this.state.selectedIndex === 0
                    ? moment().hour()
                    : null
                }
                data={this.state.selectedData[this.state.selectedIndex]}
                hideTooltipOnDragEnd={true}
                tooltipComponent={
                  <Tooltip
                    theme={{
                      label: {
                        color: "white",
                        fontSize: 12,
                        fontWeight: 300,
                        textAnchor: "middle",
                        opacity: 1,
                        dx: 0,
                        dy: 0,
                      },
                      shape: {
                        width: 45,
                        height: 45,
                        opacity: 1,
                        dx: 0,
                        dy: 4,
                        rx: 50,
                        color: Colors.Primary,
                      },
                    }}
                  />
                }
                theme={{
                  stroke: {
                    color: Colors.Primary,
                    width: 4,
                    opacity: 0.4,
                  },
                  scatter: {
                    default: {
                      width: 10,
                      height: 10,
                      rx: 4,
                      color: Colors.Primary,
                      opacity: 0.8,
                    },
                    selected: { color: Colors.Primary },
                  },
                }}
                smoothing="cubic-spline"
              />
              <Area
                data={this.state.selectedData[this.state.selectedIndex]}
                theme={{
                  gradient: {
                    from: { color: "grey", opacity: 0.01 },
                    to: { color: "grey", opacity: 0.01 },
                  },
                }}
                smoothing="cubic-spline"
              />
          </Chart>
constructor(props) {
    super(props);

    this.state = {
      datePicker: moment().unix(),
      trackDateModal: false,
      selectedData: [this.props.day, this.props.week, this.props.month, this.props.year],
      selectedDataEntryAverage: [this.props.dayAverage, this.props.weekAverage, this.props.monthAverage, this.props.yearAverage],
      selectedIndex: 1
    };

    this.updateIndex = this.updateIndex.bind(this);
  }

When all y-values are zero, I get numerous errors including:

image

image

image

If more context is needed, please let me know. Thank you.

lindan4 commented 2 years ago

I am following up to ask if you have looked into the issue. Please let me know. Thank you.

faizantariq1 commented 2 years ago

@lindan4 did you find the solution?