【问题标题】:How to convert JSON to Html in a React App如何在 React 应用程序中将 JSON 转换为 Html
【发布时间】:2021-01-29 11:59:28
【问题描述】:

如何在 react 应用中将 JSON 转换为带有 h​​tml 元素的普通 html?

请注意,如果您不知道要注入的 HTML 字符串中的内容,那么 dangerouslySetInnerHTML 可能会很危险

根据反应文档-

dangerouslySetInnerHTML 是 React 在 浏览器 DOM。一般来说,从代码中设置 HTML 是有风险的,因为 很容易无意中将您的用户暴露给跨站点脚本 (XSS) 攻击。所以,你可以直接从 React 设置 HTML,但是你有 输入 dangerouslySetInnerHTML 并使用 __html 传递一个对象 关键,提醒自己这是危险的。

我在下面创建了一个代码沙箱: https://codesandbox.io/s/relaxed-sunset-tlmr2?file=/src/App.js

输出只是呈现为字符串而不是 html 元素。

这是我的代码:

import React from "react";
import "./styles.css";

const blocks = {
  time: 1602725895949,
  blocks: [
    {
      type: "header",
      data: {
        text: "This is a heading",
        level: 2
      }
    },
    {
      type: "paragraph",
      data: {
        text: "This is a paragraph"
      }
    }
  ]
};

export default function App() {
  function convertToHtml({ blocks }) {
    console.log(blocks);
    var convertedHtml = "";
    blocks.map((block) => {
      switch (block.type) {
        case "header":
          convertedHtml += `<h${block.data.level}>${block.data.text}</h${block.data.level}>`;
          break;
        case "paragraph":
          convertedHtml += `<p>${block.data.text}</p>`;
          break;
        default:
          console.log("Unknown block type", block.type);
          break;
      }
    });

    return <React.Fragment>{convertedHtml}</React.Fragment>;
  }

  return (
    <div className="App">
      <h1>JSON to html below</h1>
      {convertToHtml(blocks)}
    </div>
  );
}

【问题讨论】:

  • 这能回答你的问题吗? Insert HTML with React Variable Statements (JSX)
  • 您必须直接返回 JSX 而不是将其设为字符串。我会在几分钟后发布答案。
  • @diedu 我编辑了这个问题以表明根据反应文档不推荐危险的SetInnerHTML。您发布的答案使用危险的SetInnerHTML

标签: reactjs


【解决方案1】:

当您在 React 中生成 HTML 时,您不想将其视为字符串,而是希望将其视为组件。您可以返回 &lt;p&gt;{block.data.text}&lt;/p&gt; 而不是返回文字字符串 '&lt;p&gt;${block.data.text}&lt;/p&gt;',它是有效的 JSX。

我已将您的 switch 语句转换为呈现单个块的函数组件。请注意,null 是不渲染任何内容的组件的标准返回值。对于动态生成 h1h2 等的情况,我将该字符串保存为大写字母变量,以便 React 将其解释为自定义组件而不是内置元素。

export function Block({ type, data }) {
  switch (type) {
    case "header":
      const Element = "h" + data.level;
      return <Element>{data.text}</Element>;
    case "paragraph":
      return <p>{data.text}</p>;
    default:
      console.log("Unknown block type", type);
      return null;
  }
}

然后您可以循环遍历块数组并将每个块作为道具传递给Block 组件。每当你从循环中返回元素时,如果你没有设置key,react 会抛出一个警告,所以我使用数组索引作为键。

export default function App() {
  return (
    <div className="App">
      <h1>JSON to html below</h1>
      {blocks.blocks.map((block, i) => (
        <Block key={i} {...block} />
      ))}
    </div>
  );
}

Code Sandbox Link

【讨论】:

    【解决方案2】:

    我有另一个答案。

    试试这个。现在没有危险的 HTML 内容了。

    import parse from "html-react-parser";
    
    return <React.Fragment>{parse(convertedHtml)}</React.Fragment>;
    

    包裹:https://codesandbox.io/examples/package/html-react-parser

    同一个Code Sandbox

    https://codesandbox.io/s/modern-glitter-1nnkc?file=/src/App.js:27-65

    【讨论】:

    • 我赞成你的回答,但我真的尽量避免安装更多的包。我希望可能有一种 jsx 方式来做到这一点。
    • 你可以使用React.createElement('div', {}, 'text')代替连接字符串
    【解决方案3】:

    您必须使用属性dangerouslySetInnerHTML

    像这样:

    return <React.Fragment>{<div dangerouslySetInnerHTML={{ __html: convertedHtml }} />}</React.Fragment>;
    

    我还为您的Code Sandbox 提供了解决方案: https://codesandbox.io/s/modern-glitter-1nnkc?file=/src/App.js:1542-1674

    如果有效则标记为答案。 谢谢

    【讨论】:

    • 根据 react docs,这不是一个好习惯 - 很容易无意中将您的用户暴露给跨站点脚本 (XSS) 攻击,您可以直接从 React 设置 HTML,但您必须键入取出 dangerouslySetInnerHTML 并使用 __html 键传递一个对象,以提醒自己它很危险。
    猜你喜欢
    • 2015-11-18
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 2021-04-03
    • 2018-06-15
    相关资源
    最近更新 更多