1

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;

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

Is there a problem with the way I'm calling the Bar component? I'm trying to avoid editing it because it's part of the template I'm using and I assume it works. Could it be caused by the context I'm calling the component from?
2

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.

1 Comment

Is there a problem with the way I'm calling the Bar component? I'm trying to avoid editing it because it's part of the template I'm using and I assume it works. Could it be caused by the context I'm calling the component from?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.