Accepting an SVG as a prop to a React component - reactjs

I am working on a React component that needs to accept an SVG as a prop.
I have a default svg in case the prop is not provided, but if it is provided then the default svg can be replaced out with the one accepted from prop.
So the component is like.
<MySvg src={path to svg or the svg itself} height={20} width={20} fillColor={'red'} />
All that the component should do is display this SVG with the provided props. I expect the DOM to be something like this.
<svg fill={this.props.fillColor} height={this.props.height} width={this.props.width}>
<g>
<rect />
</g>
</svg>
Since each SVG is different, meaning it might have a polygon, rect, g, etc., what is the best way to achieve this?
2 things I am looking for?
Loading an svg from a path and applying the props (color, height, width)?
If src prop has the SVG itself, how do we display that and apply the props (color, height, width)
Update: I tried out one of the approach in the answers below, but it does not seem to work. Here is a link to a CodeSandbox I have in place - codesandbox.io/s/n0yzv9yyvp

I worked with SVG in react.js a lot, the best solution I found is to use embed svg:
<MySvg src={'/path/to/svg'} height={20} width={20} fillColor={'red'} />
And inside your component
<svg fill={this.props.fillColor} height={this.props.height} width={this.props.width}>
<g>
<image
x="10"
y="197"
width="159"
height="113"
xlinkHref={this.props.src}
/>
</g>
</svg>
x, y, width and height are usual parameters of the image svg tag, you can omit or rewrite them as you want

Your best bet will be to use data URIs.
Example:
<img src='data:image/svg+xml;utf8,<svg ... > ... </svg>'>
Read more here:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs

you can pass props to svg components just like any other components
for example
function App() {
return <Svg height={20} width={20} fill={black} />;
}
const Svg = ({ height, width, color }) => (
<svg
height={height}
width={width}
fill={color}
xmlns="http://www.w3.org/2000/svg"
></svg>
);

Related

Multiple color fill on SVG as component in React

I can change the fill of an SVG using it as a component
import { ReactComponent as Icon} from '../assets/icon.svg'
...
<Icon fill='#000' />
With "current" on the fill field inside the SVG file
<path fill="current" />
But I have two differents path. How can I set them to have differents fills?
<path fill="current" />
<path fill="otherColor?" />
I managed to use different colors by creating a component that return that SVG as JSX passing colors as props
const Icon = ({inside, outside}) => (
<svg>
<g>
<path fill={outside} />
<path fill={inside} />
</g>
</svg>
)
<Icon outside='#000' inside='red'/>

How to render an svg logo in React-pdf document in the dom?

I have a project, where I am using React-pdf to generate a document. I want to add an SVG logo to this document. According to the React-pdf documentation, they have an element called
Svg that is a container that defines a new coordinate system and viewport, and it is used as the outermost element of SVG documents. From what I understand I should somehow convert a normal svg to the type of element that React-pdf uses, in order to make it work? (If so, how could I accomplish this? Can I use some sort of external library?). My code is below(Now it gives me an error because I can`t use the Image from React-pdf to render svg. If I use the Image element with src of an image that is in the format .jpeg or .png it works.
import {
Page,
Text,
View,
Document,
StyleSheet,
Image,
Svg,
PDFViewer,
} from "#react-pdf/renderer";
...
return (
<div>
<PDFViewer style={{ width: "98vw", height: "98vh" }}>
<Document title="TITLE" author="AUTHOR">
<Page size="A4" style={styles.page}>
<View style={styles.section}>
<Svg>
<Image src={logoUrl} style={styles.logo} />
</Svg>
<Text>My PDF</Text>
</View>
</Page>
</Document>
</PDFViewer>
</div>
);
...
An easy way to do this is to put your SVG file in a folder in your React Project. And then import it into your app.js or wherever you need it using an img tag
import myIcon from 'icons/myIcon.svg';
import {
Page,
Text,
View,
Document,
StyleSheet,
Image,
Svg,
PDFViewer,
} from "#react-pdf/renderer";
import myIcon from 'icons/myIcon.svg'
...
return (
<div>
<PDFViewer style={{ width: "98vw", height: "98vh" }}>
<Document title="TITLE" author="AUTHOR">
<Page size="A4" style={styles.page}>
<View style={styles.section}>
//CALL YOUR SVG USING IMG TAG
<img src={myIcon} />
<Text>My PDF</Text>
</View>
</Page>
</Document>
</PDFViewer>
</div>
);
...
I replaced your SVG TAG with <img src={myIcon} />
You will need to use actual svg code and any svg related tags. It is all documented pretty well here: https://react-pdf.org/svg
Example in React:
import React from 'react';
import {
Svg,
Polygon,
Rect,
Page,
Document,
} from '#react-pdf/renderer';
const ExampleSvg = () => (
<Svg width="200" height="200" viewBox="-100 -100 200 250">
<Polygon points="0,0 80,120 -80,120" fill="#234236" />
<Polygon points="0,-40 60,60 -60,60" fill="#0C5C4C" />
<Polygon points="0,-80 40,0 -40,0" fill="#38755B" />
<Rect x="-20" y="120" width="40" height="30" fill="#A32B2D" />
</Svg>
);
const PdfToShow = () => (
<Document>
<Page size="A4">
<ExampleSvg />
</Page>
</Document>
);
export default PdfToShow;
This is very old but, as far as I can see the Element from react pdf expects actual svg code, you are giving it and img tag which is invalid.
Image Magick can convert your svg to a png. This answer might help: How to convert a SVG to a PNG with ImageMagick?

React component inside an SVG element

I want to embed a custom react component inside an SVG but it's not working. Is it even allowed in an SVG? if not, are there workarounds?
Below is my code, trying to insert the Modal component:
<polygon
id="Paris"
<Modal show={show} handleClose={hideModal}>
<p>Modal</p>
<p>Data</p>
</Modal>
<button type="button" onClick={showModal}>
open
</button>
stroke="#010101"
fill="rgb(251, 106, 106)"
stroke-width="2"
stroke-miterlimit="10"
points="1596.182,374.685 .../>
What I am trying to accomplish is to display a popup when we click on a province inside an svg map.
For what your are trying to achieve, I will wrap svg's inside the modal. Something like this:
<Modal>
<svg></svg>
</Modal>
In your modal component, make sure to display svg as children:
return (
<Fragment>
{props.children}
</Fragment>
);
Take a look in the doc for more info: https://reactjs.org/docs/composition-vs-inheritance.html
Following #Robert Longson's comment, I inserted the Modal component inside a foreignObject and it works. Still the Modal window needs to be adjusted manually as far as the x, y coordinates are concerned so that it pops up exactly over the clicked svg element:
<foreignObject x="58%" y="6%" width="200px" height="250px">
<Modal show={show} handleClose={hideModal}>
<p style={{ padding: "10px" }}>Modal</p>
<p>Data</p>
</Modal>
</foreignObject>
Please note that you must set the x,y, height, width attributes for this to work, as documented in this answer React - html tags inside svg

Custom label on Recharts radar chart

I'm Having a hell of a time trying to get custom labels on a recharts radar chart working. I've tried doing multiple things according to the docs so I figured I'd throw it to the wolves. Hopefully one of you can point me in the right direction.
<ResponsiveContainer>
<RadarChart outerRadius={125} cy={175} data={ucRadarData}>
<Legend verticalAlign='top' height={36} />
<PolarGrid />
<PolarAngleAxis dataKey='value'>
<Label content={({ value }) => <Typography>{value}</Typography>} /> // When I remove this component, the labels get removed as well so I assume this is the component I want to target.
</PolarAngleAxis>
<PolarRadiusAxis domain={[lowestRangeStart, highestRangeEnd]} tickCount={tickArray.length} />
<Radar label={({ label }) => <Typography>{label}</Typography>} name='Self Assessment' dataKey='Self' stroke='#8884d8' fill='#8884d8' fillOpacity={0.6} /> // Also tried adding custom label here.
</RadarChart>
</ResponsiveContainer>
Do this:
Make a render function for custom tick and add that as tick prop to your PolarAngleAxis component
function customTick({ payload, x, y, textAnchor, stroke, radius }) {
return (
<g
className="recharts-layer recharts-polar-angle-axis-tick"
>
<text
radius={radius}
stroke={stroke}
x={x}
y={y}
className="recharts-text recharts-polar-angle-axis-tick-value"
text-anchor={textAnchor}
>
<tspan x={x} dy="0em">
{payload.value}
</tspan>
</text>
</g>
);
}
<PolarAngleAxis dataKey='value' tick={customTick}/>

SVG embedded using <object> tag does not render in React app

I am trying to show a svg based on a props value in a React component. I can show this using image tag, but using object tag does not work.
So, this works-->
<svg {...props}>
<image width="100%" xlinkHref={`/${props.svg}`}/>
</svg>
But this does not-->
<object {...props} type="image/svg+xml" data={`/${props.svg}`} />
props have height, width, x, y and the svg image url to be rendered.
I want to render the svg as an svg and not as an image, how can I achieve it?

Resources