Reaccionar - ¿Cómo pasar etiquetas HTML en accesorios?


118

Quiero poder pasar texto con etiquetas HTML, así:

<MyComponent text="This is <strong>not</strong> working." />

Pero dentro del MyComponentmétodo de renderizado de, cuando imprimo this.props.text, literalmente imprime todo:

This is <strong>not</strong> working.

¿Hay alguna forma de hacer que React analice HTML y lo descargue correctamente?


¿Cuál es su función de render real?
Lucio

3
El patrón típico sería convertir el contenido en elementos secundarios de su componente <MyComponent>This is <strong>not</strong> working</MyComponent>, en lugar de pasarlos como accesorios. ¿Podría dar más contexto sobre lo que realmente está tratando de lograr?
Nick Tomlin

Casi la misma pregunta: Reactjs se convierte a html .
totymedli

Respuestas:


140

Puede usar matrices mixtas con cadenas y elementos JSX (consulte los documentos aquí ):

<MyComponent text={["This is ", <strong>not</strong>,  "working."]} />

Aquí hay un violín que muestra que funciona: http://jsfiddle.net/7s7dee6L/

Además, como último recurso, siempre tiene la capacidad de insertar HTML sin procesar, pero tenga cuidado porque eso puede exponerlo a un ataque de secuencias de comandos entre sitios (XSS) si no está saneando los valores de propiedad.


10
Esto funciona, excepto que ahora recibo una advertencia: Advertencia: cada niño en una matriz o iterador debe tener un accesorio de "clave" único. Comprueba el método de renderizado de CTA. Se le pasó a un niño de Template1. Consulte fb.me/react-warning-keys para obtener más información.
ffxsam

3
Puede hacer que este error desaparezca revisando la matriz y agregando el índice como clave en MyComponent. {text.map( textOrHTML, index) => <span key={index}>{textOrHTML}</span> )} Aunque, es tan extraño que tengamos que hacer esto en primer lugar por completo.
HussienK

5
También puede corregir la advertencia colocando key="[some unique value]"el <strong>elemento.
Chad Johnson

Bien, funcionando bien, me gustaría saber cómo podría usar una variable dentro de strong en lugar de la cadena 'not'
Jaison

2
Para eliminar la advertencia de clave de matriz, ahora también es posible pasar un solo JSX como este. <MyComponent text={<>This is <strong>not</strong> working.</>} />
Arif

111

En realidad, hay varias formas de hacerlo.

Quieres usar JSX dentro de tus accesorios

Simplemente puede usar {} para hacer que JSX analice el parámetro. La única limitación es la misma que para todos los elementos JSX: debe devolver solo un elemento raíz.

myProp={<div><SomeComponent>Some String</div>}

La mejor manera legible de hacerlo es crear una función renderMyProp que devolverá componentes JSX (como la función de render estándar) y luego simplemente llamar a myProp = {this.renderMyProp ()}

Quieres pasar solo HTML como una cadena

De forma predeterminada, JSX no le permite representar HTML sin formato a partir de valores de cadena. Sin embargo, hay una forma de hacerlo:

myProp="<div>This is some html</div>"

Luego, en su componente, puede usarlo así:

<div dangerouslySetInnerHTML=myProp={{ __html: this.renderMyProp() }}></div>

Tenga en cuenta que esta solución 'puede' abrirse en ataques de falsificación de secuencias de comandos entre sitios. También tenga en cuenta que solo puede renderizar HTML simple, sin etiquetas o componentes JSX u otras cosas sofisticadas.

La forma de matriz

En reaccionar, puede pasar una matriz de elementos JSX. Eso significa:

myProp={["This is html", <span>Some other</span>, "and again some other"]}

No recomendaría este método porque:

  • Creará una advertencia (claves faltantes)
  • No es legible
  • No es realmente el método JSX, es más un truco que un diseño intencionado.

El camino de los niños

Agregándolo en aras de la integridad, pero en reacción, también puede obtener todos los elementos secundarios que están "dentro" de su componente.

Entonces, si tomo el siguiente código:

<SomeComponent>
    <div>Some content</div>
    <div>Some content</div>
</SomeComponent>

Entonces, los dos divs estarán disponibles como this.props.children en SomeComponent y se pueden representar con la sintaxis {} estándar.

Esta solución es perfecta cuando solo tiene un contenido HTML para pasar a su Componente (Imagine un componente de Popin que solo toma el contenido de Popin como hijos).

Sin embargo, si tiene varios contenidos, no puede usar niños (o necesita al menos combinarlo con otra solución aquí)


1
this.props.childrens - pero this.props.children. Sin 's' reactjs.org/docs/glossary.html#propschildren
Alexiuscrow

13

Puede usar dangerouslySetInnerHTML

Simplemente envíe el html como una cadena normal

<MyComponent text="This is <strong>not</strong> working." />

Y renderice en el código JSX así:

<h2 className="header-title-right wow fadeInRight"
    dangerouslySetInnerHTML={{__html: props.text}} />

Solo tenga cuidado si está procesando datos ingresados ​​por el usuario. Puede ser víctima de un ataque XSS

Aquí está la documentación: https://facebook.github.io/react/tips/dangerously-set-inner-html.html


7
<MyComponent text={<span>This is <strong>not</strong> working.</span>} />

y luego en su componente puede hacer la comprobación de prop así:

import React from 'react';
export default class MyComponent extends React.Component {
  static get propTypes() {
    return {
      text: React.PropTypes.object, // if you always want react components
      text: React.PropTypes.any, // if you want both text or react components
    }
  }
}

Asegúrate de elegir solo un tipo de accesorio.


6

Para mí funcionó al pasar la etiqueta html en props children

<MyComponent>This is <strong>not</strong> working.</MyComponent>


var MyComponent = React.createClass({

   render: function() {
    return (
      <div>this.props.children</div>
    );
   },


6

En una aplicación de reacción del lado del cliente, hay un par de formas de representar un prop como una cadena con algo de html. Uno más seguro que el otro ...

1 - Defina el prop como jsx (mi preferencia)

const someProps = {
  greeting: {<div>Hello<a href="/${name_profile}">${name_profile}</a></div>}
}


const GreetingComopnent = props => (
  <p>{props.someProps.greeting}</p>
)

• El único requisito aquí es que cualquier archivo que genere este accesorio debe incluir React como dependencia (en caso de que esté generando el jsx del accesorio en un archivo auxiliar, etc.).

2 - Establecer peligrosamente el innerHtml

const someProps = {
  greeting: '<React.Fragment>Hello<a href="https://stackoverflow.com/${name_profile}">${name_profile}</a></React.Fragment>'
}

const GreetingComponent = props => {
  const innerHtml = { __html: props.someProps.greeting }
  return <p dangerouslySetInnerHtml={innerHtml}></p>
}

• Se desaconseja este segundo enfoque. Imagine un campo de entrada cuyo valor de entrada se representa como un accesorio en este componente. Un usuario podría ingresar una etiqueta de secuencia de comandos en la entrada y el componente que presenta esta entrada ejecutaría este código potencialmente malicioso. Como tal, este enfoque tiene el potencial de introducir vulnerabilidades de secuencias de comandos entre sitios. Para obtener más información, consulte los documentos oficiales de React.


4

Establezca el tipo de apoyo de texto en cualquiera y haga esto:

<MyComponent text={
    <React.Fragment>
        <div> Hello, World!</div>
    </React.Fragment>
    } 
/>

Ejemplo


3

Puede hacerlo de 2 formas que yo sepa.

1- <MyComponent text={<p>This is <strong>not</strong> working.</p>} />

Y luego haz esto

class MyComponent extends React.Component {
   render () {
     return (<div>{this.props.text}</div>)
   }
}

O segundo enfoque, hazlo así

2- <MyComponent><p>This is <strong>not</strong> working.</p><MyComponent/>

Y luego haz esto

class MyComponent extends React.Component {
   render () {
     return (<div>{this.props.children}</div>)
   }
}

1
Agregué una variable let vhtml = "<p>Test</p>"y la usé en el accesorio de esta manera text={vhtml}y todavía se muestra en texto sin formato por alguna razón.
Si8

2

La respuesta de @matagus está bien para mí, Hope debajo del fragmento ayuda a aquellos que desean usar una variable interna.

const myVar = 'not';
<MyComponent text={["This is ", <strong>{`${myVar}`}</strong>,  "working."]} />

1

En mi proyecto, tuve que pasar un fragmento de código HTML dinámico de la variable y representarlo dentro del componente. Entonces hice lo siguiente.

defaultSelection : {
    innerHtml: {__html: '<strong>some text</strong>'}
}

El objeto defaultSelection se pasa al componente desde el .jsarchivo

<HtmlSnippet innerHtml={defaultSelection.innerHtml} />

Componente HtmlSnippet

var HtmlSnippet = React.createClass({
  render: function() {
    return (
      <span dangerouslySetInnerHTML={this.props.innerHtml}></span>
    );
  }
});

Ejemplo de Plunkr

reaccionar doc para dangerouslySetInnerHTML


1

También puede usar una función en el componente para pasar jsx a través de accesorios. me gusta:

 var MyComponent = React.createClass({

   render: function() {
    return (
      <OtherComponent
        body={this.body}
      />
    );
   },

   body() {
     return(
       <p>This is <strong>now</strong> working.<p>
     );
   }

});

var OtherComponent = React.createClass({

  propTypes: {
    body: React.PropTypes.func
  },

  render: function() {
     return (
        <section>
          {this.props.body()}
        </section>
     );
  },

});

1

Sí, puede hacerlo utilizando una matriz mixta con cadenas y elementos JSX. referencia

<MyComponent text={["This is ", <strong>not</strong>,  "working."]} />

1

El analizador de html-react-parser es una buena solución. Sólo tienes que

  • instalarlo con npm o hilo
  • importar analizador de 'html-react-parser';
  • llámalo con:

    <MyComponent text=Parser("This is <strong>not</strong> working.") />

    y funciona bien.


1

Agregando a la respuesta: si tiene la intención de analizar y ya está en JSX pero tiene un objeto con propiedades anidadas, una forma muy elegante es usar paréntesis para forzar el análisis JSX:

const TestPage = () => (
  <Fragment>
    <MyComponent property={
    {
      html: (
        <p>This is a <a href='#'>test</a> text!</p>
      )
    }}>
    </MyComponent>
  </Fragment>
);

1

Esta pregunta ya tiene muchas respuestas, pero estaba haciendo algo mal relacionado con esto y creo que vale la pena compartirlo:

Tuve algo como esto:

export default function Features() {
  return (
    <Section message={<p>This is <strong>working</strong>.</p>} />
  }
}

pero el masaje fue más largo que eso, así que intenté usar algo como esto:

const message = () => <p>This longer message is <strong>not</strong> working.</p>;

export default function Features() {
  return (
    <Section message={message} />
  }
}

Me tomó un tiempo darme cuenta de que me faltaba el () en la llamada a la función.

No funciona

<Section message={message} />

Trabajando

<Section message={message()} />

tal vez esto te ayude, ¡como a mí!


1

Puede utilizar con éxito fragmentos de React para esta tarea. Dependiendo de la versión que utiliza Reaccionar, puede utilizar la sintaxis corta: <>o la etiqueta completa: <React.Fragment>. Funciona especialmente bien si no desea envolver toda la cadena dentro de etiquetas HTML.

<MyComponent text={<>Hello World. <u>Don't be so ruthless</u>.</>} />

0

Podemos hacer lo mismo de esa manera.

const Child = () => {
  return (
     write your whole HTML here.
  )
}

ahora desea enviar este HTML dentro de otro componente cuyo nombre es Componente principal.

Llamando: -

<Parent child={<child/>} >
</Parent> 

Uso del niño: -

 const Parent = (props) => {
   const { child } = props; 
   return (
       {child}
    )
}

este trabajo perfecto para mi.


-9

He agregado el html en componentDidMount usando jQuery append. Esto deberia resolver el problema.

 var MyComponent = React.createClass({
    render: function() {

        return (
           <div>

           </div>
        );
    },
    componentDidMount() {
        $(ReactDOM.findDOMNode(this)).append(this.props.text);
    }
});

5
Esto ha sido rechazado porque no debería usar la manipulación DOM directa de jquery combinada con la manipulación DOM indirecta de react, ya que puede llevar a la eliminación del navegador.
Allison
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.