2017-02-06 3 views
0

У меня есть образец d3, который я пытаюсь интегрировать с реагированием. Компонент должен принимать массив массивов в виде точек данных (x - дата и y - значение с плавающей точкой) и отображать линейную диаграмму. Компонент выглядит следующим образом:d3 привязка к неправильному экземпляру компонента реагирует

import React, {Component} from 'react'; 
import * as d3 from "d3"; 

export default class Chart extends Component { 
    constructor(props){ 
    super(props); 
    } 

    componentDidMount(){ 
    this.buildLineChart(this.props.stock.dataset.data) 
    } 

    buildLineChart(data){ 
    var svg = d3.select("svg"), 
       margin = {top: 20, right: 20, bottom: 30, left: 50}, 
       width = +svg.attr("width") - margin.left - margin.right, 
       height = +svg.attr("height") - margin.top - margin.bottom, 
       g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

    var parseTime = d3.timeParse("%Y-%m-%d"); 

    var x = d3.scaleTime().rangeRound([0, width]); 
    var y = d3.scaleLinear().rangeRound([height, 0]); 

    var data = data.map(function(d){ 
     return [parseTime(d[0]), +d[1]] 
    }); 

    var line = d3.line() 
     .x(function(d){ 
     return x(d[0]) 
     }) 
     .y(function(d){ 
     return y(d[1]) 
     }); 

    x.domain(d3.extent(data, function(d) { return d[0]; })); 
    y.domain(d3.extent(data, function(d) { return d[1]; })); 

    g.append("g") 
     .attr("transform", "translate(0," + height + ")") 
     .call(d3.axisBottom(x)) 
     .select(".domain") 
     .remove(); 

    g.append("g") 
     .call(d3.axisLeft(y)) 
     .append("text") 
     .attr("fill", "#000") 
     .attr("transform", "rotate(-90)") 
     .attr("y", 50) 
     .attr("dy", "0.6em") 
     .attr("text-anchor", "end"); 
     // .text("Price ($)"); 

    g.append("path") 
     .datum(data) 
     .attr("fill", "none") 
     .attr("stroke", "steelblue") 
     .attr("stroke-linejoin", "round") 
     .attr("stroke-linecap", "round") 
     .attr("stroke-width", 3) 
     .attr("d", line); 

    } 

    render() { 
    const divStyle = { 
     backgroundColor: '#D8D8D8', 
     borderStyle: 'solid', 
     borderWidth: 'thin', 
     borderRadius: '15px', 
     marginLeft: '10px', 
     marginRight: '10px' 
    }; 

    return(
     <div className="form-group row col-sm-12" style={divStyle}> 
      <div className="row" id="lineChartContainer"> 
      <svg width="768" height="300"></svg> 
      </div> 
     </div> 
    ); 
    } 
} 

У меня есть компонент по умолчанию, который загружается, и все выглядит нормально. Однако, когда я создаю дополнительные экземпляры компонентов, в то время как дополнительные компоненты визуализируют, d3 записывает новую линейную диаграмму поверх старой. То, что я получаю это такая ситуацию: enter image description here

Facebook является компонент и загружает по умолчанию в порядке, но когда я пытаюсь раскрутить компонент Netflix, экземпляр генерируется, но диаграмма NFLX написано над верхней частью График Facebook. Есть ли простое соглашение, чтобы получить d3 для привязки к его собственному экземпляру компонента?

+1

Ну, я никогда не использовал реагировать и, таким образом, я, наверное, здесь не так, а просто FYI в чистом JS эту строку: ' var svg = d3.select ("svg") 'сообщает d3, чтобы выбрать ** первый ** SVG, который он находит в DOM. –

ответ

1

Вы должны выбрать элемент «SVG» внутри компонента, как показано ниже,

buildLineChart(data){ 
    var svg = d3.select(this.getDOMNode()).select("svg"), 
    .... 
} 
+0

Я должен быть в версии React, где getDOMNode устарел, поскольку у меня появилась ошибка, указывающая, что это не функция. Однако findDOMNode (this) вместо this.getDOMNode() работал, поэтому этот ответ указал мне на проблему. –