Flux
Flux

Reputation: 77

<svg> element string to React Component

Hi I am given a room object with an image id which I fetch and am returned the following

<svg id="Ebene_1" style={{"enableBackground":"new 0 0 32 32"}} version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" xmlSpace="preserve">
	<path d="M17.1,27h-10v-0.5c2.3,0,2.3-1,2.3-3.5h5.5c0,2.5,0,3.5,2.3,3.5V27z M30,6v20c0,0.6-0.4,1-1,1H18c-0.6,0-1-0.4-1-1v-4H3&#xD;&#xA;&#x9;c-0.6,0-1-0.4-1-1V9c0-0.6,0.4-1,1-1l14,0V6c0-0.6,0.4-1,1-1l11,0C29.6,5,30,5.4,30,6z M17,20h3v-9v-1h-1h-2H4v10H17z M24.8,22.5&#xD;&#xA;&#x9;c0-0.7-0.6-1.2-1.2-1.2s-1.2,0.6-1.2,1.2s0.6,1.2,1.2,1.2S24.8,23.2,24.8,22.5z M28,10h-6v1h6V10z M28,8h-7c0.6,0,1,0.4,1,1h6V8z"/>
</svg>

If I insert the returned string manually as follows into a react component (adding width and height) then the component works fine.

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>


import React, { Component } from "react";

class LoxIcon extends Component{

    render(){
        return(
            <svg width ={'200'} height ={'200'}id= "Ebene_1" style={{"enableBackground":"new 0 0 32 32"}} version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" xmlSpace="preserve">
	                <path d="M17.1,27h-10v-0.5c2.3,0,2.3-1,2.3-3.5h5.5c0,2.5,0,3.5,2.3,3.5V27z M30,6v20c0,0.6-0.4,1-1,1H18c-0.6,0-1-0.4-1-1v-4H3&#xD;&#xA;&#x9;c-0.6,0-1-0.4-1-1V9c0-0.6,0.4-1,1-1l14,0V6c0-0.6,0.4-1,1-1l11,0C29.6,5,30,5.4,30,6z M17,20h3v-9v-1h-1h-2H4v10H17z M24.8,22.5&#xD;&#xA;&#x9;c0-0.7-0.6-1.2-1.2-1.2s-1.2,0.6-1.2,1.2s0.6,1.2,1.2,1.2S24.8,23.2,24.8,22.5z M28,10h-6v1h6V10z M28,8h-7c0.6,0,1,0.4,1,1h6V8z"/>
            </svg>
        )
    }
}  
export default LoxIcon;

Given that this element is given to me dynamically how can I render it when I pass the data to the component via props, something like

import React, { Component } from "react";

class LoxIcon extends Component{

    render(){
        return(
                {this.props.svg}
   }        
  }
}  
export default LoxIcon;
  

I have tried react-inlinesvg and reactSvg npm modules but both require a file not a string

Upvotes: 2

Views: 11570

Answers (2)

Pranay Tripathi
Pranay Tripathi

Reputation: 1882

As you are passing the string representation of the html, you have to use dangerouslySetInnerHTML to set the inner html to set the svg although it is not advised as it exposes to cross site scripting, so you are better off looking for other alternatives such as setting the values as proper dom representation in the React component's render method. Just in case you want to use this method, you can try following:

class LoxIcon extends Component {
    render() {
        return (<div dangerouslySetInnerHTML={{ __html: this.props.svg }} />);
       }
    }
export default LoxIcon;

You can have further reading on dangerouslySetInnerHtml here.

Edit:

As JP4 has suggested, you can create svg object in each element of roomsData array and pass that object as the props to LoxIcon as answered by JP4. So your component will be look like:

<Grid container className={classes.root} > 
    <Grid item > 
        <Grid container alignItems={'center'} justify="center" spacing={16}> 
        {(this.props.roomsData) ? this.props.roomsData.map(room => 
            (<Grid key={room.uuid} item > <Card > <LoxIcon svg={room.svgObject} /> </Card> </Grid>)) : null} 
        </Grid> 
    </Grid>
</Grid>

Your svgObject should be like:

{
    height: value,
    width: value.
.... followed by all the properties.
}

and your LoxIcon will be like

import React from 'react';

const LoxIcon = ({ svgObject }) => (<svg width ={svgObject.width} height ={svgObject.height} id={svgObject.id} ...{all the attributes of svgObject your want to set>
<path d={svgObject.path.d}/>
</svg>);

export default LoxIcon;

Upvotes: 2

JP4
JP4

Reputation: 1176

One option could be to pass the props of the svg element into your component. If your dynamic element is not always an svg you could create some conditional rendering checking that its an svg element.

import React, { Component } from "react";

class LoxIcon extends Component{

    render(){
        return(
            <svg width={this.props.svg.width} height={this.props.svg.height} id={this.props.svg.id} style={this.props.svg.id} version={this.props.svg.id} viewBox={this.props.svg.viewBox} xmlns={this.props.svg.xmlns} x={this.props.svg.x} y={this.props.svg.y} xmlSpace={this.props.svg.xmlSpace}>
                    <path d={this.props.svg.d}/>
            </svg>
        )
    }
}  
export default LoxIcon;

Upvotes: 0

Related Questions