¿Cómo representar una cadena HTML como HTML real?

9 minutos de lectura

avatar de usuario
sergio tapia

Esto es lo que probé y cómo salió mal.

Esto funciona:

<div dangerouslySetInnerHTML={{ __html: "<h1>Hi there!</h1>" }} />

Esto no:

<div dangerouslySetInnerHTML={{ __html: this.props.match.description }} />

La propiedad de descripción es solo una cadena normal de contenido HTML. Sin embargo, se representa como una cadena, no como HTML por alguna razón.

ingrese la descripción de la imagen aquí

¿Alguna sugerencia?

avatar de usuario
Ilano

Es this.props.match.description una cadena o un objeto? Si es una cadena, debería convertirse a HTML sin problemas. Ejemplo:

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'));

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

Sin embargo, si la descripción es <h1 style="color:red;">something</h1> sin las comillas ''obtendrás:

​Object {
$$typeof: [object Symbol] {},
  _owner: null,
  key: null,
  props: Object {
    children: "something",
    style: "color:red;"
  },
  ref: null,
  type: "h1"
}

Si es una cadena y no ve ningún marcado HTML, el único problema que veo es un marcado incorrecto.

ACTUALIZAR

Si está tratando con entidades HTML, debe decodificarlas antes de enviarlas a dangerouslySetInnerHTML por eso se llama “peligrosamente” 🙂

Ejemplo de trabajo:

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'));

  • this.props.match.description es una cadena, no un objeto. ¿Qué quieres decir con marcado incorrecto? ¿Te refieres a etiquetas sin cerrar? React debería simplemente renderizarlo, ¿no?

    –Sergio Tapia

    28/09/2016 a las 22:31

  • ¿Podría pegar aquí console.log(this.props.match.description);

    – Ilano

    28/09/2016 a las 22:32

  • Un ejemplo: &lt;p&gt;&lt;strong&gt;Our Opportunity:&lt;/strong&gt;&lt;/p&gt;

    –Sergio Tapia

    28/09/2016 a las 22:33

  • En este caso, debe usar .innerHTML o decodificar HTMLEntities.

    – Ilano

    28/09/2016 a las 22:58

  • Devuelve varias líneas o código HTML con etiquetas: function htmlDecode(input){ var e = document.createElement(‘div’); e.innerHTML = entrada; var cadena de retorno = ”; for (index = 0; index < e.childNodes.length; index++) { // caso de solo una cadena if(e.childNodes[index].nodeValue){ returnString += e.childNodes[index].valor de nodo; } // caso de HTML if(e.childNodes[index].outerHTML){ returnString += e.childNodes[index].outerHTML; } } devuelve cadena de retorno; }

    – Chris Adams

    2 de enero de 2020 a las 15:38


avatar de usuario
pixelearth

Yo uso ‘react-html-parser’

yarn add react-html-parser
import ReactHtmlParser from 'react-html-parser'; 

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

Fuente en npmjs.com

Levantando el comentario de @okram para más visibilidad:

de su descripción de github: Convierte cadenas HTML directamente en componentes React evitando la necesidad de usar peligrosamente SetInnerHTML de npmjs.com Una utilidad para convertir cadenas HTML en componentes React. Evita el uso peligroso de SetInnerHTML y convierte elementos HTML estándar, atributos y estilos en línea en sus equivalentes de React.

  • ¿Esta biblioteca usa “dangerouslySetInnerHTML” en segundo plano?

    – Omar

    9 de octubre de 2019 a las 5:51

  • de su descripción de github: Converts HTML strings directly into React components avoiding the need to use dangerouslySetInnerHTML de npmjs.com A utility for converting HTML strings into React components. Avoids the use of dangerouslySetInnerHTML and converts standard HTML elements, attributes and inline styles into their React equivalents.

    – okram

    2 de enero de 2020 a las 19:12

  • Para React 17.0+, uso una biblioteca similar llamada “html-react-parser”, que actualmente es compatible. npmjs.com/package/html-react-parser

    –Marty McGee

    5 de febrero de 2021 a las 14:24

  • De la sección de preguntas frecuentes de html-react-parser: “esta biblioteca no es segura para XSS (secuencias de comandos entre sitios)”. npmjs.com/package/html-react-parser

    – Aniket Suryavanshi

    11 mayo 2021 a las 10:42

  • Es posible que deba instalar con: npm install react-html-parser

    – james.c.funk

    14 mayo 2021 a las 13:52

avatar de usuario
sergio flores

Verifique si el texto que está tratando de agregar al nodo no se escapa de esta manera:

var prop = {
    match: {
        description: '&lt;h1&gt;Hi there!&lt;/h1&gt;'
    }
};

En lugar de esto:

var prop = {
    match: {
        description: '<h1>Hi there!</h1>'
    }
};

si se escapa, debe convertirlo desde el lado del servidor.

El nodo es texto porque se escapa

El nodo es texto porque se escapa

El nodo es un nodo dom porque no se escapa

El nodo es un nodo dom porque no se escapa

  • Este era el problema. La cadena de descripción se escapó de HTML. Lo desescapé y ahora funciona bien.

    –Sergio Tapia

    29 de septiembre de 2016 a las 0:03

  • Por favor, evite usar dangerouslySetInnerHTML en su lugar usa Fragment de reaccionar v16. Verifique la siguiente respuesta de @brad-adams

    – Kunal Parek

    22 de mayo de 2018 a las 4:42

  • Agradezco la mención @KunalParekh, pero son cosas diferentes. Mi respuesta solo es válida si el html se encuentra dentro de su aplicación (lo que significa que en realidad es JSX). Para analizar HTML de una fuente externa a jsx, debe buscar otra solución.

    – Brad Adams

    5 de marzo de 2019 a las 22:42

avatar de usuario
Kandarp

Si tiene HTML en una cadena, recomendaría usar un paquete llamado html-react-parser.

Instalación

MNP:

npm install html-react-parser

hilo:

yarn add html-react-parser

Uso

import parse from 'html-react-parser'
const yourHtmlString = '<h1>Hello</h1>'

código:

<div>
    {parse(yourHtmlString)}
</div>

Si tiene control sobre el origen de la cadena que contiene html (es decir, en algún lugar de su aplicación), puede beneficiarse del nuevo <Fragment> API, haciendo algo como:

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>
}

  • No hay una cadena que contenga html en su ejemplo. Es jsx o cadena simple.

    – mrkvon

    19 de diciembre de 2018 a las 18:36

  • Bueno, sí, técnicamente tienes razón @mrkvon, sin embargo, como mencioné, esto solución solo es válido si dicho “html”/jsx es algo sobre lo que tiene control. No por renderizar algunos crudo html proporcionado a través de una API, por ejemplo. Antes de la Fragment API siempre fue un dolor para mí, eso requería más span envolturas que a veces interfieren con los diseños flexibles. Cuando me topé con esta pregunta buscando una posible solución, pensé en compartir cómo yo sortear las cosas.

    – Brad Adams

    25 de enero de 2019 a las 21:26

  • ¡Gracias! Esta fue la única solución que funcionó en mi caso. Además, respondiendo al comentario de mrkvon sobre esta respuesta: esta respuesta contiene html, es decir Some text <strong>wrapped with strong</strong> contiene etiqueta html strong.

    – Binita Bharati

    15 de noviembre de 2019 a las 12:39

  • @BinitaBharati Pero eso no es una cadena. Si obtiene una cadena de una API como “

    Esto es una cadena

    ” (o simplemente almacena una cadena en una variable), cuando coloque esta cadena en , la salida seguirá conteniendo el < p> etiqueta.

    – Muchacalcomanía

    23 de marzo de 2020 a las 22:53

  • @BradAdams. Aunque buen truco. Puedo ver los casos en los que se vuelve útil.

    – Muchacalcomanía

    24 de marzo de 2020 a las 18:20

Uso innerHTML junto con una referencia para abarcar:

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>
}

ACTUALIZAR:

Eliminé algunos estados HTML y agregué comentarios para que el ejemplo fuera más preciso en torno al concepto.

/**
 * 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>
}

  • No hay una cadena que contenga html en su ejemplo. Es jsx o cadena simple.

    – mrkvon

    19 de diciembre de 2018 a las 18:36

  • Bueno, sí, técnicamente tienes razón @mrkvon, sin embargo, como mencioné, esto solución solo es válido si dicho “html”/jsx es algo sobre lo que tiene control. No por renderizar algunos crudo html proporcionado a través de una API, por ejemplo. Antes de la Fragment API siempre fue un dolor para mí, eso requería más span envolturas que a veces interfieren con los diseños flexibles. Cuando me topé con esta pregunta buscando una posible solución, pensé en compartir cómo yo sortear las cosas.

    – Brad Adams

    25 de enero de 2019 a las 21:26

  • ¡Gracias! Esta fue la única solución que funcionó en mi caso. Además, respondiendo al comentario de mrkvon sobre esta respuesta: esta respuesta contiene html, es decir Some text <strong>wrapped with strong</strong> contiene etiqueta html strong.

    – Binita Bharati

    15 de noviembre de 2019 a las 12:39

  • @BinitaBharati Pero eso no es una cadena. Si obtiene una cadena de una API como “

    Esto es una cadena

    ” (o simplemente almacena una cadena en una variable), cuando coloque esta cadena en , la salida seguirá conteniendo el < p> etiqueta.

    – Muchacalcomanía

    23 de marzo de 2020 a las 22:53

  • @BradAdams. Aunque buen truco. Puedo ver los casos en los que se vuelve útil.

    – Muchacalcomanía

    24 de marzo de 2020 a las 18:20

avatar de usuario
hou soune

Simplemente usa el método peligrosamente SetInnerHTML de React

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

O puede implementar más de esta manera fácil: Renderiza el HTML sin procesar en la aplicación React

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad