Home > Back-end >  React JS - Component rendering in infinite loop
React JS - Component rendering in infinite loop

Time:10-24

When I render a screen with the Bar component it renders in an infinite loop, even before I attempt to pass data. I've imported react-chartjs-2 to test and that works fine, i.e. loads just once. But the other bar chart appears to render, then continues to do so until my browser crashes.

I'm thinking it may be related to the fact that my component is a const.

//import Bar from 'react-chartjs-2';   // <-- Renders once
import Bar from './../charts/Bar.js';  // <-- Renders in a loop

const MyComponent = () => {

    return (
        <div className="search">
            <Bar/>
        </div>
    );

}
export default MyComponent;

This is the Bar component I'm using. It's from a Themeforest template called Gogo-React.

/* eslint-disable prefer-rest-params */
import React, { useEffect, useRef, useState } from 'react';
import { Chart } from 'chart.js';

import { barChartOptions } from './config';

const Bar = ({ data, shadow = false }) => {
  const chartContainer = useRef(null);
  const [, setChartInstance] = useState(null);

  useEffect(() => {
    if (chartContainer && chartContainer.current) {
      if (shadow) {
        Chart.defaults.global.datasets.barWithShadow =
          Chart.defaults.global.datasets.bar;
        Chart.defaults.barWithShadow = Chart.defaults.bar;
        Chart.controllers.barWithShadow = Chart.controllers.bar.extend({
          draw(ease) {
            Chart.controllers.bar.prototype.draw.call(this, ease);
            const {
              chart: { ctx },
            } = this;
            ctx.save();
            ctx.shadowColor = 'rgba(0,0,0,0.2)';
            ctx.shadowBlur = 7;
            ctx.shadowOffsetX = 5;
            ctx.shadowOffsetY = 7;
            ctx.responsive = true;
            Chart.controllers.bar.prototype.draw.apply(this, arguments);
            ctx.restore();
          },
        });
      }
      const context = chartContainer.current.getContext('2d');
      const newChartInstance = new Chart(context, {
        type: shadow ? 'barWithShadow' : 'bar',
        options: barChartOptions,
        data,
      });
      setChartInstance(newChartInstance);
    }
  }, [chartContainer, data, shadow]);

  return <canvas ref={chartContainer} />;
};

export default Bar;

CodePudding user response:

useEffect is listening to chartContainer. then useEffect is running and changing canvas and chartContainer ref then useEffect is triggered. This will cause a loop.

CodePudding user response:

The useEffect() hook in React is called every time the state of dependencies change, you bar is calling the useEffect() hook repeatedly because of the chartContianer state getting updated.

Better way of doing this is to update the data in the chart and not the entire chart itself.

  • Related