React + d3.js-svg使用新的道具重新渲染上一个

时间:2019-01-25 22:13:50

标签: reactjs d3.js svg

我正在尝试使用从API提取的数据来绘制简单的条形图。创建第一个图表后,当带有数据的道具更改时,组件会重新渲染,但是旧图表并不会消失。

我相信这与d3.js和反应在dom处理方面的不同有关,但是我对d3的了解非常有限。我可以做些什么来使旧的svg在道具更改后消失并重新呈现?

下面是组件代码。

class BarChart extends React.Component {

constructor(props) {
    super(props);
    this.state = {
        fetchedData: [],
    };
    this.createBarChart = this.createBarChart.bind(this);
    this.fetchRequiredData = this.fetchRequiredData.bind(this);
}

fetchRequiredData() {
  //fetches data and assigns it to components state, then calls createBarChart() in callback

}

componentDidMount() {
    this.fetchRequiredData();
}

componentDidUpdate(prevProps) {
    if (this.props !== prevProps) {
        this.fetchRequiredData();
    }
}

createBarChart() {
    const node = this.node;

    const width = this.props.size[0];
    const height = this.props.size[1];

    const chart = select(node).append('g')
        .attr('transform', `translate(${30}, ${10})`);

    const xScale = scaleBand()
        .range([0, width])
        .domain(this.state.fetchedData.map((s) => s.analyte))
        .padding(0.2);

    const yScale = scaleLinear()
        .range([height, 0])
        .domain([0, 100]);

    const makeYLines = () => axisLeft()
        .scale(yScale);

    chart.append('g')
        .attr('transform', `translate(0, ${height})`)
        .call(axisBottom(xScale));
    chart.append('g')
        .call(axisLeft(yScale));

    chart.append('g')
        .attr('class', 'grid')
        .call(makeYLines()
            .tickSize(-width, 0, 0)
            .tickFormat('')
        );

    const barGroups = chart.selectAll()
        .data(this.state.fetchedData)
        .enter()
        .append('g');

    barGroups
        .append('rect')
        .attr('class', 'bar')
        .attr('x', (g) => xScale(g.analyte))
        .attr('y', (g) => yScale(g.value))
        .attr('height', (g) => height - yScale(g.value))
        .attr('width', xScale.bandwidth());

    barGroups
        .append('text')
        .attr('class', 'value')
        .attr('x', (a) => xScale(a.analyte) + xScale.bandwidth() / 2)
        .attr('y', (a) => yScale(a.value) + 30)
        .attr('text-anchor', 'middle')
        .text((a) => `${a.value}%`);
}

render() {
    return (
        <div>
            <svg ref={node => this.node = node}
                 height={550} width={600}>
            </svg>
        </div>
    )
}

1 个答案:

答案 0 :(得分:0)

我认为 this.state.fetchedData 代替了 this.props

componentDidUpdate(prevProps) {
    if (this.state.fetchedData !== prevProps.fetchedData ) {
        this.fetchRequiredData();
    }
}