1

I know this is more of the question regarding javascript than d3.js specific, but I am confused regardless.

I have two same function in d3.js that I would like to add.

.on("mouseover", function(){
  d3.select(this)
    .attr("fill", "orange")
})

and

.on("mouseover", ()=>{
  d3.select(this)
    .attr("fill", "orange")
})

They are both trying to achieve the same thing. Make the box that has mouse hovered to orange.

But second one returns me error

Uncaught TypeError: this.setAttribute is not a function

I assume the issue is coming from interpretation of this. I tried to understand it with other articles, but I am not understanding what the difference is. Should I stop using arrow function?

I appreciate your input.

EDIT :

I was pointed to this stack over flow link. While this does explain the lexical this, it is not clear why d3.js has issue with this.

Shintaro Takechi
  • 1,215
  • 1
  • 17
  • 39

1 Answers1

1

This article article explained the high level reason.

Arrow functions also have a lexical this. This usually comes in handy, but it introduces some caveats when working with D3. Normally, when you pass a function to most D3 APIs (like selection.attr) it will bind this to the DOM element being operated on. That won't work with arrow functions, so you have two choices of how to work around it.

So the reason was because selection that is passed to the .on was using this as DOM element. He further explains

to define your arrow function so that it accepts a third parameter.

So I changed my arrow function version to following :

.on("mouseout", (d,i,nodes)=>{
  d3.select(nodes[i])
    .attr("fill", "orange")
})

And now it works as I intended

Further looking into the source code of d3.js, .on is implemented with use of each, each is implemented by using callback.call with node being first argument (hence this is different from expected). Which is what he is stating.

Shintaro Takechi
  • 1,215
  • 1
  • 17
  • 39