1

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.

setAttribute error message

0

1 Answer 1

2

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)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.