道具更改后,Chart中的SVG不会重新呈现。反应+ d3

时间:2019-01-11 07:00:34

标签: reactjs d3.js svg

尝试使用d3.js创建一个简单的条形图。我也继续前进,并提供了一个按钮来创建随机数据,以用作svg条形图的数据集。但是,svg中的条仅针对第一个数据集渲染。即使我更改了数据集的值,条形图仍保持不变。需要帮助。

我检查了道具,看它们是否在变化。道具正在更新,但没有改变图表中的条形图。

App.js文件:

 class App extends Component {
  constructor(props){
      super(props)
      this.state={
        dataSet: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
      }
  }

  dataSetCreator = () =>{
    let n = Math.ceil(Math.random()*10);
    this.setState({
      dataSet : [...Array(n)].map(_=>Math.ceil(Math.random()*10))
    })
  }


  render() {
    console.log(this.state.dataSet)
    return (
      <div className="App">
       <div className="d3-chart">
         <span>Bar Chart With D3</span>
       <BarChart  
        data={this.state.dataSet}
        height={500}
        width={500}/>
        <button onClick={()=>this.dataSetCreator()}>Change Data</button>
        </div>
      </div>
    );
  }
}

BarChart.js:

class BarChart extends Component{
    componentDidMount(){
        this.createBarChart();
    }

    componentDidUpdate(){
        this.createBarChart();
    }

    createBarChart = ()=>{
        const svgWidth = this.props.width
        const svgHeight = this.props.height;

        var svg = d3.select('svg')
                .attr('width', svgWidth)
                .attr('height', svgHeight)
                .attr('class', 'bar-chart');
        debugger
        var dataset = this.props.data;
        var barPadding = 5;
        var barWidth = (svgWidth / dataset.length);

       svg.selectAll('rect')
                       .data(dataset)
                       .enter()
                       .append('rect')
                       .attr('y', (d)=>svgHeight-(d*5))
                       .attr('height', (d)=>d*5)
                       .attr('width', barWidth-barPadding)
                       .attr('transform', (d, i)=>{
                           var translate = [barWidth*i, 0];
                           return "translate(" + translate + ")"
                       })


    }

    render(){
        console.log(this.props.data)
        return(
            <svg>

            </svg>
        );
    }
}

1 个答案:

答案 0 :(得分:0)

您需要遵循createBarChart中的general update pattern

createBarChart = () => {

    const svgWidth = this.props.width
    const svgHeight = this.props.height;

    var svg = d3.select('svg')
      .attr('width', svgWidth)
      .attr('height', svgHeight)
      .attr('class', 'bar-chart');

    var dataset = this.props.data;
    var barPadding = 5;
    var barWidth = (svgWidth / dataset.length);

    var rects = svg.selectAll('rect')
      .data(dataset)

    var rectsEnter = rects.enter()
      .append('rect')
      .attr('y', (d) => svgHeight - (d * 5))
      .attr('height', (d) => d * 5)
      .attr('width', barWidth - barPadding)
      .attr('transform', (d, i) => {
        var translate = [barWidth * i, 0];
        return "translate(" + translate + ")"
      })

    rects.attr('y', (d) => svgHeight - (d * 5))
      .attr('height', (d) => d * 5)
      .attr('width', barWidth - barPadding)
      .attr('transform', (d, i) => {
        var translate = [barWidth * i, 0];
        return "translate(" + translate + ")"
      })
    rects.exit().remove();
  }

我还有一个问题,即Array.map无法在stackblitz中的[...Array(n)]上无法正常工作,因此不得不更改dataSetCreator(我不确定这是否适用于您的环境)。

  dataSetCreator = () => {
    let n = Math.ceil(Math.random() * 10);
    let newData = Array.from({ length: n }, () => Math.floor(Math.random() * 39));
    this.setState({
      dataSet: newData
    })
  }

stackblitz