0

I am working on a reactjs project - where there will be notification/chat services being polled every 20-60 seconds.

I've noticed though - that when this polling is activated other elements on the page like d3.js charts get re-triggered to render, even though there is no obvious difference or change to the data on componentWillReceiveProps.

this.fetchUpdates();

let waitToCheck = 10000;
setTimeout(() => {
  console.log("START CHECKING!!");

  let timerToCheckChat = setInterval(() => this.fetchUpdates(), waitToCheck);

  if(!getUserDetails()){
    clearTimeout(timerToCheckChat);
  }

}, waitToCheck);

this is an example of a roundchart --

import React from 'react';
import * as d3 from 'd3';
import './RoundChart.scss';

class RoundChart extends React.Component {
    constructor(props) {
        super(props);
        this.myRef = React.createRef();
        this.state = {
            data: this.props.data? this.props.data: [],
            theme: this.props.theme ? this.props.theme : ['#bde0fe', '#2698f9', '#71bcfd', '#f1f8fe']
        };
    }

    componentWillReceiveProps(nextProps) {
      // You don't have to do this check first, but it can help prevent an unneeded render
      if (nextProps.data !== this.state.data) {
        //console.log("PROPS HAVE CHANGED FOR CHART");        
        this.setState({ data: nextProps.data });
        this.buildChart();
      }
    }

    componentDidMount() {
        this.buildChart();
    }

    buildChart(){
        var $this = this.myRef.current;

        d3.select($this)
            .selectAll('svg')
            .remove();

        var data = this.state.data;

        var width = parseInt(this.props.width, 10),
            height = parseInt(this.props.height, 10),
            radius = parseInt(this.props.r, 10);

        var color = d3.scaleOrdinal().range(this.state.theme);

        var svg = d3
            .select($this)
            .append('svg')
            .attr('width', width)
            .attr('height', height)
            .append('g')
            .attr('class', 'piechart')
            .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');

        svg.append("circle")
            .attr("cx", 0)
            .attr("cy", 0)
            .attr('fill', function(d, i) {
                return color(i);
            })
            .attr("r", radius);

        svg.append("text")
            .data(data)
            .attr("x", 0)
            .attr("y", 0)
            .attr("text-anchor", "middle")
            .attr("dominant-baseline", "central")
            .text(0)
            .transition()
            .duration(3000)
            .tween("text",function(d) {
                var self = this;
                var i = d3.interpolate(this.textContent, d.value);
                var prec = (d + "").split(".");
                var round = (prec.length > 1) ? Math.pow(10, prec[1].length) : 1;

                return function(t) {
                    self.textContent = Math.round(i(t) * round) / round;
                }; 

                //typing text animation
                /*var self = this;
                var newText = "hellob"//d.value;
                var textLength = newText.length;
                return function(t) {
                    self.textContent = newText.slice(0, Math.round(t * textLength));
                };*/
            });
    }

    render() {
        return <div ref={this.myRef} className="RoundChart" />;
    }
}
export default RoundChart;
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
The Old County
  • 89
  • 13
  • 59
  • 129

1 Answers1

0

Try this way

componentWillReceiveProps(nextProps) {
    // You don't have to do this check first, but it can help prevent an unneeded render
    if (JSON.stringify(nextProps.data) !== JSON.stringify(this.state.data)) {
      //console.log("PROPS HAVE CHANGED FOR CHART");        
      this.setState({ data: nextProps.data }, ()=> {
        this.buildChart();
      });
    }
}
Henry Le
  • 421
  • 3
  • 6
  • I will try this - you think the objects are slightly different? – The Old County Feb 24 '21 at 10:17
  • You can read more https://stackoverflow.com/questions/1068834/object-comparison-in-javascript. Your problem I think the reason is you are not using callback for setState, so when run buildChart the state will not receive the latest data – Henry Le Feb 24 '21 at 10:38
  • I think its also the way I've invoked the charts -- as they will render before a call was made to get the data -- then render again to change the value -- but this was ok when its a 0 count and then 10 – The Old County Feb 24 '21 at 11:14
  • In one instance -- the data is changing - by the chart itself to calculate angles - so it did keep replenishing/refreshing because of that bug – The Old County Feb 24 '21 at 11:15