TypeError: this.setAttribute is not a function

。_饼干妹妹 提交于 2020-01-16 04:16:39

问题


I'm new to d3 and reactjs. I was trying to make a bar chart with following Rect.js componenet

I've tried to debug right before // enter-update but with no avail.

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>
    )
  }
}

The error message is TypeError: this.setAttribute is not a function; When I debug, I found the error only appears when I have attr chained after merge(this.rects) but I don't understand why.


回答1:


Here is a minimal example of the issue:

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.

The issue is straightforward: the merged selection isn't what you think it is.

The selection rect is a selection of placeholder nodes created by .enter() - not actual nodes in the DOM. They have a few methods, but no method for setting attributes. This is why the above code, or your code, will produce the error: this.setAttribute is not a function, as setAttribute is not a method of an entered placeholder (see the source here).

Instead we just drop the first .enter() statement. Which will also lead to the behavior you want, as we probably don't want rect to be an enter selection, since we do exit and update after. Instead we want rect to be a selection of existing rect elements, not placeholders. Modifying the above we get to account for this change we get:

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

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

rect.exit()....

Or with your code:

  // 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)


来源:https://stackoverflow.com/questions/57315527/typeerror-this-setattribute-is-not-a-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!