React callback click event `this` undefined

I am using d3 and react to create charts. Clicking a button will update the chart. In the component for the chart is an onclick event listener, however the "this" keeps getting mixed up

One method with arrow functions returns Uncaught TypeError: node.getAttribute is not a function:

 this.setupButtons= function() {
          d3.select('#toolbar')
            .selectAll('.buttons')
            .on('click',  ()=> {
              d3.selectAll('.buttons').classed('active', false);
              var button = d3.select(this);

              button.classed('active', true);

              var buttonId = button.attr('id');

                this.toggleDisplay(buttonId)
            });
        }
*/

This is of course because the this refers to the component instance. So I researched how to refer to the click event and found that using e or event.target is supposed to solve the issue. In react, however, an error is returned: Uncaught TypeError: Cannot read property 'target' of undefined

 this.setupButtons= function() {
              d3.select('#toolbar')
                .selectAll('.buttons')
                .on('click',  (e)=> {
                  d3.selectAll('.buttons').classed('active', false);
                  var button = d3.select(e.target);

                  button.classed('active', true);

                  var buttonId = button.attr('id');


                    this.toggleDisplay(buttonId)
                });
            }

Both this.setupButtons and this.toggleDisplay() are defined in the same method, which belongs to a component.

EDIT: This question does not appear to be a "duplicate" of the question provided.This was an issue of D3's handling of event, not the use of this, apparently. The solution to this question (add d3.event.target instead of event.target) is not provided as an answer in the question this supposedly duplicates.

2 answers

  • answered 2019-08-13 03:54 Dafang Cao

    Assign var that = this in the outer function. Now you have a way to reference the outer this.

    this.setupButtons = function () {
        var that = this;
        d3.select('#toolbar')
            .selectAll('.buttons')
            .on('click', function() {
                d3.selectAll('.buttons').classed('active', false);
                var button = d3.select(this);
    
                button.classed('active', true);
    
                var buttonId = button.attr('id');
    
                that.toggleDisplay(buttonId)
            });
    }
    

  • answered 2019-08-13 04:00 Chandrani Chatterjee

    You can store the reference of the outer this into another variable. I generally store it into a variable like var that = this and then you can reference the variable that wherever required.

    this.setupButtons= function() {
              var that = this;
              d3.select('#toolbar')
                .selectAll('.buttons')
                .on('click',  ()=> {
                  d3.selectAll('.buttons').classed('active', false);
                  var button = d3.select(that);
    
                  button.classed('active', true);
    
                  var buttonId = button.attr('id');
    
                    that.toggleDisplay(buttonId)
                });
            }