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.
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!
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With