Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 component does not re-draw after receiving new props

Tags:

reactjs

d3.js

I am building an small app on React.js and I am using D3 to draw cubes corresponding to props it receives.

class Visual extends React.Component {

renderD3 = (records, selector) => {
    const data = records;
    console.log('inside renderD3', data);
    // It logs out most updated props every time it receives new props

    const visual = this.props.connectFauxDOM('div', selector);
    d3
        .select(visual)
        .attr('class', 'visual-wrapper')
        .selectAll('div')
        .data(data) // bind data
        .enter()
        .selectAll('div') 
        .data(d => d3.range(d.duration / 5).map(() => d)) 
        .enter()
        .append('div')
        .attr('class', 'block')
        .style('background-color', d => d.color);
}

componentDidMount() {
// it is just for generating gray grids for background setting, please ignore 
    this.renderD3([{duration: 300, color: '#e6e6e6'}], 'defaultBox')
}
render() {
    this.renderD3(this.props.records, 'box')
    return (
        <div>
            <div className="line-container">{this.props.defaultBox}</div>
            <div className="line-container">{this.props.box}</div>
        </div>
    );
}

}

What I want to achieve is that once visual component receives new props, D3 re-draws with new color(new props have different colors).

so far, inside renderD3 function, it receives new props and on console, it does log new props correctly but cubes still have same color. The thing is that if I hash-refresh, then the color changes as in D3 draws cubes with new props.

I have imagined that D3 cubes will redraw (or update) cubes automatically once Visual component re-renders every time it receives new props. But thought inside renderD3 function, it receives new props and logs new props on every re-render, D3 cubes do not change.

I am fairly comfortable with react but have little understanding of D3. I am using react-faux-dom for integrating d3 with react by the way.

I'd appreciate any insight.

Thank you in advance.

like image 581
heathercoraje Avatar asked Oct 20 '25 08:10

heathercoraje


2 Answers

So you're using the connectFauxDOM tool which is really reserved for animations when you don't need them, as far as I can tell? (I could be wrong here...)

There's a known issue with the documentation, it's not clear that you don't need to use this tool. You should just be able to use the normal stateless API:

const ReactFauxDOM = require('react-faux-dom');

class Visual extends React.Component {
  renderD3 = (data) => {
    console.log('inside renderD3', data);
    // It logs out most updated props every time it receives new props

    const el = ReactFauxDOM.createElement('div');

    d3.select(el)
      .attr('class', 'visual-wrapper')
      .selectAll('div')
      .data(data) // bind data
      .enter()
      .selectAll('div') 
      .data(d => d3.range(d.duration / 5).map(() => d)) 
      .enter()
      .append('div')
      .attr('class', 'block')
      .style('background-color', d => d.color);

    return el.toReact();
  }

  render() {
    return (
      <div>
        <div className="line-container">{this.renderD3(this.props.records)}</div>
      </div>
    );
  }
}

If you're intending on using animations, you will need connectFauxDOM. If you don't need to do that sort of thing then the normal createElement and then toReact flow should be a lot easier to work with. I hope this helps!

like image 123
Olical Avatar answered Oct 22 '25 01:10

Olical


let divs = d3
    .select(visual)
    .attr('class', 'visual-wrapper')
    .selectAll('div')
    .data(data) // bind data
    .enter()
    .selectAll('div') 
    .data(d => d3.range(d.duration / 5).map(() => d));

    divs.enter()
    .append('div')
    .attr('class', 'block')

    //update
    divs.style('background-color', d => d.color);

For update you will need to break the code like this in your render method.

Reference: here

like image 38
Cyril Cherian Avatar answered Oct 21 '25 23:10

Cyril Cherian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!