reactjs - parser - Reaccionar: ¿cómo pasar etiquetas HTML en accesorios?
html to jsx (16)
Quiero poder pasar texto con etiquetas HTML, así:
<MyComponent text="This is <strong>not</strong> working." />
Pero dentro del
MyComponent
de
MyComponent
de
MyComponent
, cuando
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?
¿Hay alguna razón por la que nadie haya sugerido react-html-parser? Parece una buena forma de trabajar con HTML importado sin tener que hacerlo peligrosamente
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>
);
Desde React v16.02 puedes usar un Fragment.
<MyComponent text={<Fragment>This is an <strong>HTML</strong> string.</Fragment>} />
Más información: https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html
El analizador de html-react-parser es una buena solución. Sólo tienes que
- instalarlo con npm o hilo
- importar analizador desde ''html-react-parser'';
-
llámalo con:
<MyComponent text=Parser("This is <strong>not</strong> working.") />
y funciona bien
En mi proyecto, tuve que pasar un fragmento 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 archivo
.js
<HtmlSnippet innerHtml={defaultSelection.innerHtml} />
Componente HtmlSnippet
var HtmlSnippet = React.createClass({
render: function() {
return (
<span dangerouslySetInnerHTML={this.props.innerHtml}></span>
);
}
});
En realidad, hay varias formas de hacerlo.
Desea usar JSX dentro de sus accesorios
Simplemente puede usar {} para hacer que JSX analice el parámetro. La única limitación es la misma que para cada elemento 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 devuelva componentes JSX (al igual que la función de renderización estándar) y luego simplemente llame a myProp = {this.renderMyProp ()}
Desea pasar solo HTML como una cadena
Por defecto, JSX no le permite renderizar HTML sin formato a partir de valores de cadena. Sin embargo, hay una manera 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 scripts entre sitios. También tenga en cuenta que solo puede renderizar HTML simple, sin etiqueta o componente JSX u otras cosas elegantes.
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 (faltan claves)
- No es legible
- No es realmente la forma JSX, es más un truco que un diseño previsto.
El camino de los niños
Agregándolo por completo pero en reacción, también puede hacer que todos los niños que están ''dentro'' de su componente.
Entonces, si tomo el siguiente código:
<SomeComponent>
<div>Some content</div>
<div>Some content</div>
</SomeComponent>
Luego, 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 Popin que solo toma el contenido de Popin como hijos).
Sin embargo, si tiene múltiples contenidos, no puede usar niños (o necesita al menos combinarlo con otra solución aquí)
En una aplicación de reacción del lado del cliente, hay un par de formas de representar un accesorio como una cadena con algo de html. Uno más seguro que el otro ...
1 - Definir el accesorio 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 esté generando este accesorio debe incluir React como una 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="/${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 script en la entrada y el componente que procesa 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
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);
}
});
La respuesta de @matagus está bien para mí, espero que debajo del fragmento se ayude a aquellos que desean usar una variable dentro.
<MyComponent text={["This is ", <strong>not</strong>, "working."]} />
Para mí funcionó al pasar la etiqueta html en accesorios niños
<MyComponent>This is <strong>not</strong> working.</MyComponent>
var MyComponent = React.createClass({
render: function() {
return (
<div>this.props.children</div>
);
},
Puede usar peligrosamenteSetInnerHTML
Simplemente envíe el html como una cadena normal
<MyComponent text="This is <strong>not</strong> working." />
Y renderizar en el código JSX de esta manera:
<h2 className="header-title-right wow fadeInRight"
dangerouslySetInnerHTML={{__html: props.text}} />
Solo tenga cuidado si está procesando datos ingresados por el usuario. Puedes ser víctima de un ataque XSS
Aquí está la documentación: https://facebook.github.io/react/tips/dangerously-set-inner-html.html
Puede usar matrices mixtas con cadenas y elementos JSX (consulte los documentos here ):
<MyComponent text={["This is ", <strong>not</strong>, "working."]} />
Hay un violín aquí que muestra que funciona: http://jsfiddle.net/7s7dee6L/
Además, como último recurso, siempre tiene la capacidad de insertar HTML sin formato, pero tenga cuidado porque eso puede abrirlo a un ataque de secuencias de comandos entre sitios (XSS) si no está desinfectando los valores de propiedad.
Puedes hacerlo de 2 maneras 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>)
}
}
Sí, puede hacerlo utilizando una matriz de mezcla con cadenas y elementos JSX. reference
const myVar = ''not'';
<MyComponent text={["This is ", <strong>{`${myVar}`}</strong>, "working."]} />
También podría 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>
);
},
});
<MyComponent text={<span>This is <strong>not</strong> working.</span>} />
y luego en su componente puede hacer la comprobación de utilería de la siguiente manera:
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 utilería.