React + d3.js - svg рендерит поверх предыдущего с новым реквизитом - PullRequest
0 голосов
/ 26 января 2019

Я пытаюсь отобразить простую гистограмму с данными, полученными из 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 голосов
/ 26 января 2019

Я думаю this.state.fetchedData вместо this.props

componentDidUpdate(prevProps) {
    if (this.state.fetchedData !== prevProps.fetchedData ) {
        this.fetchRequiredData();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...