Snap.svg in React – how to access the svg in a lifecycle method?

I have an svg map component which I want to update whenever the props change.
Adding and subtract classes on some of the paths… that sort of thing.

Snap.svg seemed to be the way to go. If someone knows a better way I’d like to hear it!

So here’s my render method, and the two lines marked with frowns are the ones I want to get working in a lifecycle method such as ComponentWillReceiveProps

render() {
    var map = Snap('#map');
    Snap.load("images/map.svg", function(data){
        if (map) {
            map.append(data);
            const a2047 = map.select('#a2047');               <---- :(
            a2047.attr({stroke:'yellow', strokeWidth:'6px'})  <---- :(
        }
    })

    return (
        <div className="map" id="map"/>
    );
}

The problem is, map won’t work anywhere else except inside this Snap.load callback. I tried several ways, using state, window.map, this.map… and I get errors such as ‘select is not a function’.

How to get access to the map in ComponentWillReceiveProps ?

Or is Snap.svg even the way to go for this application?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You are doing a direct DOM manipulation with Snap.svg and neither render nor componentWillReceiveProps is a good place to do that. I recommend you to do that in componentDidUpdate which calls immediately after component gets rendered. But this will not be invoked for the initial render. So we have to do this DOM manipulation in both componentDidUpdate and componentDidMount. To prevent repeating the same code, you can keep this operation in another common class method and call it from both componentDidUpdate and componentDidMount. Also, since your props have been updated at this point you can simply access them with this.props inside the new class method.

Example:

// @sigfried added to answer his comment below
import Snap from 'snapsvg-cjs';

export default class Mermaid extends Component {
  svgRender() {
    let element = Snap(this.svgDiv)
    Snap.load("images/map.svg", function(data){
      if (element) {
        element.append(data);
      }
    });
  }
  componentDidMount() {
    this.svgRender();
  }
  componentDidUpdate() {
    this.svgRender();
  }
  render() {
    return  <div ref={d=>this.svgDiv=d} />
  }
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x