类型错误:this.setAttribute 不是函数

IT技术 reactjs d3.js
2021-05-09 16:35:06

我是 d3 和 reactjs 的新手。我试图用以下 Rect.js 组件制作条形图

我之前尝试过调试,// enter-update但无济于事。

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

const dataset = [14, 68, 24500, 430, 19, 1000, 5555];
const width = 600;
const height = 400;



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

componentWillMount() {

}

componentDidMount() {
  this.renderRect();
}

componentDidUpdate() {
  this.renderRect();

}

renderRect() {
  this.container = d3.select(this.refs.container);


  // draw refs rectangle
  this.rects = this.container.selectAll("bar")
                            .data(dataset)
                            .enter();
  // exit
  this.rects.exit().remove();

  // enter-update
  this.rects = this.rects.enter()
                         .append("rect")
                         .merge(this.rects)
                         .attr("y", d => 24500 - d)
}

  render() {
    return (
      <svg ref="container" width={width} height={height}>

      </svg>
    )
  }
}

错误信息是TypeError: this.setAttribute is not a function; 当我调试时,我发现错误只在我attr链接之后出现,merge(this.rects)但我不明白为什么。

setAttribute 错误信息

1个回答

这是该问题的一个最小示例:

var rect = container.selectAll("rect")
  .data([1,2,3])
  .enter();   // return a selection of entered placeholders

var merge = rect.enter() // return a selection of entered placeholders
  .append("rect") // return a selection of appended nodes
  .merge(rect)    // merge appended nodes with entered placeholders.
  .attr("someAttribute",0); // set an attribute for both appended nodes and entered placeholders.

问题很简单:合并的选择不是您认为的那样。

选择rect是由创建的占位符节点的选择.enter()- 不是 DOM 中的实际节点。他们有一些方法,但没有设置属性的方法。这就是为什么上面的代码或您的代码会产生错误:this.setAttribute is not a function, as setAttributeis not an method of an input placeholder (see the source here )。

相反,我们只是删除第一个 .enter() 语句。这也将导致您想要的行为,因为我们可能不想rect成为输入选择,因为我们确实退出并在之后更新。相反,我们希望rect成为现有rect元素的选择,而不是占位符。修改上面我们得到的这个变化,我们得到:

var rect = container.selectAll("rect")
  .data([1,2,3])

rect.enter().append("rect").merge(rect)...

rect.exit()....

或者使用您的代码:

  // draw refs rectangle
  this.rects = this.container.selectAll("bar")
      .data(dataset)
      // No enter here

  // exit
  this.rects.exit().remove();

  // enter-update
  this.rects = this.rects.enter()
    .append("rect")
    .merge(this.rects)
    .attr("y", d => 24500 - d)