My goal is to fetch from my own server an SVG and to interpolate the children
attribute after the <polygon></polygon>
tag.
I am doing this is to add an interactive layer that can be modified by react.
So far I am able to achieve that by serving my SVG via react app, but I want to avoid it for security reasons.
This is my progress so far:
const App = ({children}) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#6b9bd2"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="arcs"
>
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
{children}
</svg>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
My ideal solution should look something like this:
import React, { useState, useEffect } from "react";
type ViewBox = {
x1: string;
x2: string;
y1: string;
y2: string;
};
interface SVGElement {
svgContent: string;
viewBox: ViewBox;
}
const App: React.FC = ({ children }) => {
const [content, setContent] = useState<SVGElement | undefined>();
useEffect(() => {
fetch("http://localhost:5000/get-svg-content")
.then((res) => res.json())
.then((data) => setContent(data))
.catch((e) => console.log(e));
}, []);
if (content === undefined) return <></>;
const viewBox = `${content.viewBox.x1} ${content.viewBox.x2} ${content.viewBox.y1} ${content.viewBox.y2}`;
return (
<svg viewBox={viewBox}>
{content.svgContent}
{children}
</svg>
);
};
export default App;
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
CodePudding user response:
You should consider using rehype-react
- https://github.com/rehypejs/rehype-react.
If you store your SVG as an XML in a database for example, then retrieving it as a string in the client-side, this package allows you to render same string as an SVG (or any other tag).
This method might expose you to XSS, so you should consider using react-sanitize
in order to sanitize the string before rendering it.
Using the methods mentioned above, you can render your SVG elements inside the react
client, and still implement your component logic around the rendered content.