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>
        );
    }
};
1
  • 1
    this inside componentDidMount is different from this inside the function called on the event. Commented Nov 22, 2017 at 18:25

1 Answer 1

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

2 Comments

Thanks, all the solutions worked perfectly. A little embarrassed that I couldn't get it. Thank you again.
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.

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.