如何从服务器渲染 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>

codeSandbox

您应该考虑使用 rehype-react - https://github.com/rehypejs/rehype-react.

例如,如果您将 SVG 作为 XML 存储在数据库中,然后在 client-side 中将其作为字符串检索,此包允许您呈现与 SVG 相同的字符串(或任何其他标签)。

此方法可能会让您接触到 cross-site scripting (XSS),因此您应该考虑使用 react-sanitize 以便在呈现之前清理字符串。

使用上述方法,您可以在 react 客户端中呈现 SVG 元素,并且仍围绕呈现的内容实现组件逻辑。