在React组件中将HTML字符串呈现为真实HTML

Ser*_*pia 105 html javascript jsx reactjs

这是我尝试过的以及它是如何出错的.

这有效:

<div dangerouslySetInnerHTML={{ __html: "<h1>Hi there!</h1>" }} />
Run Code Online (Sandbox Code Playgroud)

这不是:

<div dangerouslySetInnerHTML={{ __html: this.props.match.description }} />
Run Code Online (Sandbox Code Playgroud)

description属性只是HTML内容的普通字符串.然而,由于某种原因,它被渲染为字符串,而不是HTML.

在此输入图像描述

有什么建议?

Ila*_*nus 80

确实this.props.match.description是一个字符串或一个对象?如果它是一个字符串,它应该转换为HTML就好了.例:

class App extends React.Component {

constructor() {
    super();
    this.state = {
      description: '<h1 style="color:red;">something</h1>'
    }
  }

  render() {
    return (
      <div dangerouslySetInnerHTML={{ __html: this.state.description }} />
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)

结果:http://codepen.io/ilanus/pen/QKgoLA?editors = 1011

但是,如果description: <h1 style="color:red;">something</h1>没有引号,''您将得到:

?Object {
$$typeof: [object Symbol] {},
  _owner: null,
  key: null,
  props: Object {
    children: "something",
    style: "color:red;"
  },
  ref: null,
  type: "h1"
}
Run Code Online (Sandbox Code Playgroud)

如果它是一个字符串,你没有看到任何HTML标记,我看到的唯一问题是错误的标记..

UPDATE

如果您正在处理HTMLEntitles.你需要在发送它们之前对它们进行解码,dangerouslySetInnerHTML这就是它们危险地称之为的原因:)

工作范例:

class App extends React.Component {

  constructor() {
    super();
    this.state = {
      description: '&lt;p&gt;&lt;strong&gt;Our Opportunity:&lt;/strong&gt;&lt;/p&gt;'
    }
  }

   htmlDecode(input){
    var e = document.createElement('div');
    e.innerHTML = input;
    return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
  }

  render() {
    return (
      <div dangerouslySetInnerHTML={{ __html: this.htmlDecode(this.state.description) }} />
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)


Ser*_*res 31

检查您尝试附加到节点的文本是否没有像这样转义:

var prop = {
    match: {
        description: '&lt;h1&gt;Hi there!&lt;/h1&gt;'
    }
};
Run Code Online (Sandbox Code Playgroud)

而不是这个:

var prop = {
    match: {
        description: '<h1>Hi there!</h1>'
    }
};
Run Code Online (Sandbox Code Playgroud)

如果被转义,你应该从服务器端转换它.

节点是文本,因为它是转义的

节点是文本,因为它是转义的

节点是dom节点,因为没有转义

节点是dom节点,因为没有转义

  • 感谢提及@KunalParekh,但它们是不同的东西。我的回答仅当 html 位于您的应用程序中时才有效(意味着它实际上是 JSX)。要将来自外部源的 HTML 解析为 jsx,您需要寻求另一种解决方案。 (5认同)
  • 这就是问题所在。描述字符串是转义的 HTML。我对它进行了转义,现在它工作正常。 (3认同)
  • 请避免使用`dangerouslySetInnerHTML`而不是使用反应v16中的`Fragment`.查看@ brad-adams的[下一个答案](/sf/answers/3484427481/) (2认同)

pix*_*rth 25

我用了'react-html-parser'

yarn add react-html-parser
Run Code Online (Sandbox Code Playgroud)
import ReactHtmlParser from 'react-html-parser'; 

<div> { ReactHtmlParser (html_string) } </div>

Run Code Online (Sandbox Code Playgroud)

来源上npmjs.com

  • 这个库在后台使用“dangerouslySetInnerHTML”吗? (14认同)
  • 对于 React 17.0+,我使用一个名为“html-react-parser”的类似库,目前支持该库。https://www.npmjs.com/package/html-react-parser (9认同)
  • 来自 html-react-parser 的 FAQ 部分:“这个库不是 XSS(跨站脚本)安全的。” https://www.npmjs.com/package/html-react-parser (8认同)
  • 来自其 github 描述:````将 HTML 字符串直接转换为 React 组件,避免使用 npmjs.com 中的危险的SetInnerHTML``````用于将 HTML 字符串转换为 React 组件的实用程序。避免使用危险的SetInnerHTML并将标准HTML元素、属性和内联样式转换为其React等效项。``` (4认同)
  • 这是最好的答案。 (2认同)
  • 这应该是问题的实际答案。不管怎么说,还是要谢谢你。 (2认同)

Bra*_*ams 13

如果您可以控制包含html的字符串的来源(即应用程序中的某个位置),您可以从新<Fragment>API中受益,执行以下操作:

import React, {Fragment} from 'react'

const stringsSomeWithHtml = {
  testOne: (
    <Fragment>
      Some text <strong>wrapped with strong</strong>
    </Fragment>
  ),
  testTwo: `This is just a plain string, but it'll print fine too`,
}

...

render() {
  return <div>{stringsSomeWithHtml[prop.key]}</div>
}
Run Code Online (Sandbox Code Playgroud)

  • 您的示例中没有包含html的字符串.它是jsx或普通字符串. (7认同)
  • @BinitaBharati 但这不是一个字符串。如果您从 API 中获取一个字符串,如“&lt;p&gt;This is a String&lt;/p&gt;”(或者只是将字符串存储在变量中),当您将此字符串放入 &lt;Fragment&gt; 中时,输出仍将包含 &lt; p&gt; 标签。 (3认同)
  • 好吧,从技术上来说,您是正确的@mrkvon,但是正如我所提到的,此_solution_仅在您说“ html” / jsx是您可以控制的情况下才有效。例如,不用于渲染通过API提供的_raw_ html。在使用“ Fragment” API之前,对我来说一直很痛苦,需要附加的“ span”包装,这些包装有时会与flex布局混淆。当我偶然发现这个问题以寻找可能的解决方案时,我想我会分享_I_如何解决问题的。 (2认同)
  • 谢谢!这是对我的案例唯一有效的解决方案。另外,回应mrkvon对此答案的评论:这个答案确实包含html,即“一些文本&lt;strong&gt;用strong包裹&lt;/strong&gt;”包含html标签“strong”。 (2认同)

Kan*_*arp 10

如果字符串中有 HTML,我建议使用名为html-react-parser.

安装它:npm install html-react-parser或者如果你使用纱线,yarn add html-react-parser

像这样使用它

import parse from 'html-react-parser'
const yourHtmlString = '<h1>Hello</h1>'
Run Code Online (Sandbox Code Playgroud)
<div>
    {parse(yourHtmlString)}
</div>
Run Code Online (Sandbox Code Playgroud)

参考:https : //www.npmjs.com/package/html-react-parser

  • 谢谢,这也适用于 Next.JS (2认同)

小智 9

您只需使用 React 的危险的SetInnerHTML 方法

<div dangerouslySetInnerHTML={{ __html: htmlString }} />

或者你可以用这个简单的方法实现更多:在 React 应用程序中渲染 HTML 原始数据


Lor*_*ana 7

我将 innerHTML 与一个 ref 一起使用来跨越:

import React, { useRef, useEffect, useState } from 'react';

export default function Sample() {
  const spanRef = useRef<HTMLSpanElement>(null);
  const [someHTML,] = useState("some <b>bold</b>");

  useEffect(() => {
    if (spanRef.current) {
      spanRef.current.innerHTML = someHTML;
    }
  }, [spanRef.current, someHTML]);

  return <div>
    my custom text follows<br />
    <span ref={spanRef} />
  </div>
}
Run Code Online (Sandbox Code Playgroud)

更新

我删除了 someHTML 状态并添加了注释以使示例更加符合概念。

/**
 * example how to retrieve a reference to an html object
 */

import React, { useRef, useEffect } from 'react';

/**
 * this component can be used into another for example <Sample/>
 */
export default function Sample() {
    /**
     * 1) spanRef is now a React.RefObject<HTMLSpanElement>
     * initially created with null value
     */
    const spanRef = useRef<HTMLSpanElement>(null);

    /**
     * 2) later, when spanRef changes because html span element with ref attribute,
     * follow useEffect hook will triggered because of dependent [spanRef].
     * in an if ( spanRef.current ) that states if spanRef assigned to valid html obj
     * we do what we need : in this case through current.innerHTML
     */
    useEffect(() => {
        if (spanRef.current) {
            spanRef.current.innerHTML = "some <b>bold</b>";
        }
    }, [spanRef]);

    return <div>
        my custom text follows<br />
        {/* ref={spanRef] will update the React.RefObject `spanRef` when html obj ready */}
        <span ref={spanRef} />
    </div>
}
Run Code Online (Sandbox Code Playgroud)


Sal*_*one 5

就我而言,我使用了react-render-html

首先通过安装包npm i --save react-render-html

然后,

import renderHTML from 'react-render-html';

renderHTML("<a class='github' href='https://github.com'><b>GitHub</b></a>")
Run Code Online (Sandbox Code Playgroud)