如何从服务器渲染 SVG 并且仍然可以选择将 JSX 插入其中?
how to render an SVG from a server and still have the option to interpolate JSX into it?
我的目标是从我自己的服务器获取 SVG 并在 <polygon></polygon>
标签后插入 children
属性。
我这样做是为了增加一个可以被react修改的交互层
到目前为止,我可以通过 React 应用程序提供我的 SVG 来实现这一点,但出于安全原因我想避免它。
这是我目前的进度:
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>
我理想的解决方案应该是这样的:
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>
您应该考虑使用 rehype-react
- https://github.com/rehypejs/rehype-react.
例如,如果您将 SVG 作为 XML 存储在数据库中,然后在 client-side 中将其作为字符串检索,此包允许您呈现与 SVG 相同的字符串(或任何其他标签)。
此方法可能会让您接触到 cross-site scripting (XSS),因此您应该考虑使用 react-sanitize
以便在呈现之前清理字符串。
使用上述方法,您可以在 react
客户端中呈现 SVG 元素,并且仍围绕呈现的内容实现组件逻辑。
我的目标是从我自己的服务器获取 SVG 并在 <polygon></polygon>
标签后插入 children
属性。
我这样做是为了增加一个可以被react修改的交互层
到目前为止,我可以通过 React 应用程序提供我的 SVG 来实现这一点,但出于安全原因我想避免它。
这是我目前的进度:
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>
我理想的解决方案应该是这样的:
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>
您应该考虑使用 rehype-react
- https://github.com/rehypejs/rehype-react.
例如,如果您将 SVG 作为 XML 存储在数据库中,然后在 client-side 中将其作为字符串检索,此包允许您呈现与 SVG 相同的字符串(或任何其他标签)。
此方法可能会让您接触到 cross-site scripting (XSS),因此您应该考虑使用 react-sanitize
以便在呈现之前清理字符串。
使用上述方法,您可以在 react
客户端中呈现 SVG 元素,并且仍围绕呈现的内容实现组件逻辑。