React - Como passar tags HTML em props?


118

Eu quero ser capaz de passar texto com tags HTML, assim:

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

Mas dentro do MyComponentmétodo de render de, quando eu imprimo this.props.text, ele literalmente imprime tudo:

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

Existe alguma maneira de fazer o React analisar o HTML e descartá-lo corretamente?


Qual é a sua função real de renderização?
Lucio

3
O padrão típico seria tornar seu conteúdo filho de seu componente <MyComponent>This is <strong>not</strong> working</MyComponent>, em vez de passá-los como acessórios. Você poderia dar mais contexto sobre o que você está realmente tentando realizar?
Nick Tomlin,

Quase a mesma pergunta: Reactjs convertem para html .
totymedli

Respostas:


140

Você pode usar matrizes mistas com strings e elementos JSX (consulte a documentação aqui ):

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

Há um violino aqui que mostra que ele está funcionando: http://jsfiddle.net/7s7dee6L/

Além disso, como último recurso, você sempre tem a capacidade de inserir HTML bruto, mas tome cuidado porque isso pode abrir você para um ataque de script entre sites (XSS) se não estiver higienizando os valores das propriedades.


10
Isso funciona, exceto que agora recebo um aviso: Aviso: Cada filho em uma matriz ou iterador deve ter uma propriedade de "chave" exclusiva. Verifique o método de renderização do CTA. Foi passado um filho do Template1. Consulte fb.me/react-warning-keys para obter mais informações.
ffxsam

3
Você pode fazer esse erro desaparecer examinando o array e adicionando o índice como uma chave em MyComponent. {text.map( textOrHTML, index) => <span key={index}>{textOrHTML}</span> )} Embora seja tão estranho que tenhamos que fazer isso inteiramente em primeiro lugar.
HussienK

5
Você também pode corrigir o aviso colocando key="[some unique value]"o <strong>elemento.
Chad Johnson

Bom, funcionando bem, gostaria de saber como eu poderia usar uma variável dentro de forte em vez de string 'não'
Jaison

2
Para remover o aviso de chave de array, agora também é possível passar um único JSX como este. <MyComponent text={<>This is <strong>not</strong> working.</>} />
Arif

111

Na verdade, existem várias maneiras de fazer isso.

Você quer usar JSX dentro de seus adereços

Você pode simplesmente usar {} para fazer com que JSX analise o parâmetro. A única limitação é a mesma para cada elemento JSX: ele deve retornar apenas um elemento raiz.

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

A maneira mais legível de fazer isso é criar uma função renderMyProp que retornará componentes JSX (assim como a função de renderização padrão) e, em seguida, simplesmente chamar myProp = {this.renderMyProp ()}

Você quer passar apenas HTML como string

Por padrão, JSX não permite renderizar HTML bruto a partir de valores de string. No entanto, há uma maneira de fazer isso:

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

Então, em seu componente, você pode usá-lo assim:

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

Esteja ciente de que esta solução 'pode' abrir em ataques de falsificação de script entre sites. Também tome cuidado para que você só possa renderizar HTML simples, nenhuma tag JSX ou componente ou outras coisas sofisticadas.

A forma de array

Em resposta, você pode passar uma matriz de elementos JSX. Que significa:

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

Eu não recomendaria esse método porque:

  • Isso criará um aviso (chaves ausentes)
  • Não é legível
  • Não é exatamente o jeito JSX, é mais um hack do que um design pretendido.

O jeito das crianças

Adicionando-o por uma questão de integridade, mas em reação, você também pode obter todos os filhos que estão "dentro" do seu componente.

Então, se eu pegar o seguinte código:

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

Em seguida, os dois divs estarão disponíveis como this.props.children em SomeComponent e podem ser renderizados com a sintaxe {} padrão.

Esta solução é perfeita quando você tem apenas um conteúdo HTML para passar para o seu componente (imagine um componente Popin que leva apenas o conteúdo do Popin como filho).

No entanto, se você tiver vários conteúdos, não pode usar filhos (ou você precisa pelo menos combiná-los com outra solução aqui)


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

13

Você pode usar hazardouslySetInnerHTML

Basta enviar o html como uma string normal

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

E renderize no código JSX assim:

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

Apenas tome cuidado se você estiver renderizando dados inseridos pelo usuário. Você pode ser vítima de um ataque XSS

Aqui está a documentação: https://facebook.github.io/react/tips/dangerously-set-inner-html.html.html


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

e, em seu componente, você pode fazer a verificação de prop como:

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

Certifique-se de escolher apenas um tipo de suporte.


6

Para mim funcionou passando tag html em adereços infantis

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


var MyComponent = React.createClass({

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


6

Em um aplicativo de reação do lado do cliente, existem algumas maneiras de renderizar um prop como uma string com algum html. Um mais seguro que o outro ...

1 - Defina o prop como jsx (minha preferência)

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


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

• O único requisito aqui é que qualquer arquivo que esteja gerando este prop precisa incluir React como uma dependência (no caso de você estar gerando o jsx do prop em um arquivo auxiliar, etc.).

2 - Defina o innerHtml perigosamente

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

• Esta segunda abordagem é desencorajada. Imagine um campo de entrada cujo valor de entrada é renderizado como um suporte neste componente. Um usuário poderia inserir uma tag de script na entrada e o componente que renderiza essa entrada executaria esse código potencialmente malicioso. Como tal, esta abordagem tem o potencial de introduzir vulnerabilidades de script entre sites. Para obter mais informações, consulte os documentos oficiais do React


4

Defina o tipo de proposta de texto para qualquer e faça o seguinte:

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

Exemplo


3

Você pode fazer isso de duas maneiras que eu conheço.

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

E então faça isso

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

Ou segunda abordagem, assim

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

E então faça isso

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

1
Eu adicionei uma variável let vhtml = "<p>Test</p>"e usei-a no suporte como este text={vhtml}e ainda renderizado em texto simples por algum motivo.
Si8

2

A resposta @matagus é boa para mim, espero que o snippet abaixo seja ajudado aqueles que desejam usar uma variável dentro.

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

1

Em meu projeto, tive que passar um snippet html dinâmico da variável e renderizá-lo dentro do componente. Então eu fiz o seguinte.

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

O objeto defaultSelection é passado para o componente do .jsarquivo

<HtmlSnippet innerHtml={defaultSelection.innerHtml} />

Componente HtmlSnippet

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

Exemplo de Plunkr

reagir doc para hazardouslySetInnerHTML


1

Você também pode usar uma função no componente para passar jsx para os adereços. gostar:

 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

Sim, você pode fazer isso usando mix array com strings e elementos JSX. referência

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

1

Parser do html-react-parser é uma boa solução. Você só tem de

  • instale-o com npm ou yarn
  • import Parser from 'html-react-parser';
  • ligue com:

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

    e funciona bem.


1

Adicionando à resposta: se você pretende analisar e já está no JSX, mas tem um objeto com propriedades aninhadas, uma maneira muito elegante é usar parênteses para forçar a análise JSX:

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

1

Esta pergunta já tem muitas respostas, mas estava fazendo algo errado em relação a isso e acho que vale a pena compartilhar:

Eu tinha algo assim:

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

mas a massagem era mais longa do que isso, então tentei usar algo assim:

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

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

Demorei um pouco para perceber que estava faltando () na chamada de função.

Não está funcionando

<Section message={message} />

Trabalhando

<Section message={message()} />

talvez isso ajude você, como ajudou a mim!


1

Você pode utilizar fragmentos React com sucesso para esta tarefa. Dependendo da versão que você usa Reagir, você pode usar short sintaxe: <>ou a tag completa: <React.Fragment>. Funciona especialmente bem se você não quiser envolver a string inteira em tags HTML.

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

0

Podemos fazer a mesma coisa dessa maneira.

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

agora você deseja enviar este HTML dentro de outro componente cujo nome é Componente pai.

Ligando: -

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

Uso da criança: -

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

este trabalho é perfeito para mim.


-9

Anexei o html em componentDidMount usando jQuery append. Isso deve resolver o problema.

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

        return (
           <div>

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

5
Isso foi rejeitado porque você não deveria usar a manipulação direta do DOM do jquery combinada com a manipulação indireta do DOM do react, pois isso pode levar à destruição do navegador.
Allison
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.