3

I'm trying to add an event listener to a SVG path in a React component. I followed a previous Stack Overflow answer (How to access SVG elements with Javascript) that used an anonymous function, and that worked fine. When I tried to set the callback to a function defined inside the React component class, as in this Stack Overflow answer (ReactJS - Add custom event listener to component), the function is not called. Interestingly, if I make a reference to the function in the componentWillMount and use the reference, it works.

import React, { Component } from "react";

export default class ProcessMap extends Component {

    constructor(props) {
        super(props);
        this.hover = this.hover.bind(this);
    }

    componentDidMount(){
        const t = this.hover;
        let svg = document.getElementById("drawing-svg");
        svg.addEventListener("load", function() {
            let svgDoc = svg.contentDocument;
            let path1 = svgDoc.getElementById("path3372");
            //path1.addEventListener("click", this.hover, false); // this did not work
            path1.addEventListener("click", t, false); // this works
        });
    }

    hover() {
        console.log("hover");
    }

    render() {
        return (
            <div>
                <object id="drawing-svg" width="300" height="400" type="image/svg+xml" data="images/drawing.svg"></object>
            </div>
        );
    }
};
BrentJM
  • 31
  • 1
  • 4

1 Answers1

3

It isn't working since you are trying to use this inside a new regular function(), where this isn't the React component anymore.

ES6 SOLUTION

Replace

componentDidMount(){
    const t = this.hover;
    let svg = document.getElementById("drawing-svg");
    svg.addEventListener("load", function() {
        let svgDoc = svg.contentDocument;
        let path1 = svgDoc.getElementById("path3372");
        //path1.addEventListener("click", this.hover, false); // this did not work
        path1.addEventListener("click", t, false); // this works
    });
}

with an arrow function

componentDidMount(){
    const t = this.hover;
    let svg = document.getElementById("drawing-svg");
    svg.addEventListener("load", () => {
        let svgDoc = svg.contentDocument;
        let path1 = svgDoc.getElementById("path3372");
        path1.addEventListener("click", this.hover, false);
    });
}

ES5 SOLUTION

If you can't use ES6, then you can either keep track of this by storing it in a variable:

componentDidMount(){
    const t = this.hover;
    let svg = document.getElementById("drawing-svg");
    var that = this;
    svg.addEventListener("load", function() {
        let svgDoc = svg.contentDocument;
        let path1 = svgDoc.getElementById("path3372");
        path1.addEventListener("click", that.hover, false);
    });
} 

Or use .bind():

componentDidMount(){
    const t = this.hover;
    let svg = document.getElementById("drawing-svg");
    svg.addEventListener("load", (function() {
        let svgDoc = svg.contentDocument;
        let path1 = svgDoc.getElementById("path3372");
        path1.addEventListener("click", this.hover, false);
    }).bind(this));
} 
Twyx
  • 689
  • 8
  • 16
Maluen
  • 1,753
  • 11
  • 16
  • Thanks, all the solutions worked perfectly. A little embarrassed that I couldn't get it. Thank you again. – BrentJM Nov 22 '17 at 19:08
  • The way OP did it works too, just the line that is commented out doesn't. So don't think he actually needs to replace anything. – putvande Nov 08 '18 at 22:13