使用变量时危险地反应SetInnerHTML不起作用

时间:2019-01-14 15:26:36

标签: html reactjs escaping

我正在使用React创建一个SPA,以搜索数据并显示结果。每个结果都遵循以下模型

{
  "title": "A Title",
  "body": " <li>escaped html <strong>that sould be rendered</strong>.</li>
    </ul>"
}

body属性始终是应在组件中呈现的转义html。该组件如下所示:

代码

function SearchResult({ title, body, favourite }) {
  return (
    <article className="SearchResult">
    <section>
      <i className={`icon-star${favourite ? ' marked' : ''}`} />
      {title}
    </section>
    <section
      dangerouslySetInnerHTML={{ __html: body }}
      className="SearchResult-body"
    />
  </article>
  );
}

,但是每个结果的正文均未正确呈现,而是将html显示为文本 enter image description here enter image description here

问题在于,只有当我创建将变量传递给body属性的组件时,它才会发生

results.map((result, index) => (
      <SearchResult key={index} title={result.title} body={result.body} />
    ))

但是,如果我这样做,它会很好

<SearchResult
    title="A title"
    body=" &lt;li&gt;escaped html&amp;nbsp;&lt;strong&gt;that sould be rendered&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;"
  />

这为什么不同?在使用固定值时,在将值传递给默认添加的属性之前,是否应该对它进行任何预处理?

演示

可以查看此问题的演示here

1 个答案:

答案 0 :(得分:0)

似乎issue只会在您将其转义为html时出现。

@sergiotapia实现的解决方案包括创建一个辅助函数,以对html字符串进行转义以使其正常工作。

htmlDecode(content) {
  let e = document.createElement('div');
  e.innerHTML = content;
  return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}
<section
  dangerouslySetInnerHTML={{ __html: htmlDecode(body) }}
  className="SearchResult-body"
/>

不过,如@brigand所述,我会引用“ 将其转义可能会导致XSS攻击和错误的呈现。”,因此这可能不是完美的解决方案。

请参见working example