Insérer du HTML avec des instructions variables React (JSX)

204

Je construis quelque chose avec React où j'ai besoin d'insérer du HTML avec des variables React dans JSX. Existe-t-il un moyen d'avoir une variable comme ceci:

var thisIsMyCopy = '<p>copy copy copy <strong>strong copy</strong></p>';

et de l'insérer dans réagir comme ça, et ça marche?

render: function() {
    return (
        <div className="content">{thisIsMyCopy}</div>
    );
}

et le faire insérer le HTML comme prévu? Je n'ai rien vu ni entendu parler d'une fonction de réaction qui pourrait faire cela en ligne, ou d'une méthode d'analyse syntaxique qui permettrait à cela de fonctionner.

Kyle Hotchkiss
la source

Réponses:

296

Vous pouvez utiliser dangereusement SetInnerHTML , par exemple

render: function() {
    return (
        <div className="content" dangerouslySetInnerHTML={{__html: thisIsMyCopy}}></div>
    );
}
Douglas
la source
2
Comment cela fonctionne-t-il si vous devez ajouter quelque chose <head>?
Danielle Madeley
Les méthodes DOM normales dans componentDidMount devraient fonctionner, je ne l'ai pas fait auparavant cependant.
Douglas
@DanielleMadeley Essayez-vous d'insérer des commentaires IE conditionnels dans <head>? Si c'est le cas, j'ai réussi à utiliser l'astuce décrite ici: nemisj.com/conditional-ie-comments-in-react-js
Cam Jackson
3
Assurez-vous de passer une méthode à dangerouslySetInnerHTML et non un hachage. Selon les documents, il est dangereux de simplement passer un hachage. Référence: facebook.github.io/react/tips/dangerously-set-inner-html.html
criterz
1
Existe-t-il un moyen sans insérer le div?
mec
102

Notez que cela dangerouslySetInnerHTMLpeut être dangereux si vous ne savez pas ce qu'il y a dans la chaîne HTML que vous injectez. En effet, du code côté client malveillant peut être injecté via des balises de script.

C'est probablement une bonne idée de nettoyer la chaîne HTML via un utilitaire tel que DOMPurify si vous n'êtes pas sûr à 100% que le HTML que vous restituez est sûr XSS (cross-site scripting).

Exemple:

import DOMPurify from 'dompurify'

const thisIsMyCopy = '<p>copy copy copy <strong>strong copy</strong></p>';


render: function() {
    return (
        <div className="content" dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(thisIsMyCopy)}}></div>
    );
}
Yo Wakita
la source
@vsync non ça ne devrait pas :)
Artem Bernatskyi
1
est-il possible de rendre non seulement des balises html, mais aussi des balises de bibliothèque comme la balise ui Alert matérielle je veux que le code soit comme çaimport DOMPurify from 'dompurify' const thisIsMyCopy = '<Alert severity="warning">copy copy copy <strong>strong copy</strong></Alert >'; render: function() { return ( <div className="content" dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(thisIsMyCopy)}}></div> ); }
sasha romanov
@sasharomanov, Avez-vous trouvé une solution pour ce scénario?
Nimish goel
51

dangerouslySetInnerHTML présente de nombreux inconvénients car il est défini à l'intérieur de la balise.

Je vous suggère d'utiliser un wrapper React comme j'en ai trouvé un ici sur npm à cet effet. html-react-parser fait le même travail.

import Parser from 'html-react-parser';
var thisIsMyCopy = '<p>copy copy copy <strong>strong copy</strong></p>';


render: function() {
    return (
        <div className="content">{Parser(thisIsMyCopy)}</div>
    );
}

Très simple :)

user2903536
la source
3
"dangerouslySetInnerHTML présente de nombreux inconvénients car il se place à l'intérieur de la balise." Pouvez-vous expliquer plus à ce sujet. Essayer de réfléchir à la différence fondamentale qui existe entre html-react-parser et aseptisé innerHtml
dchhetri
Il semble que html-react-parser ne nettoie pas l'entrée - voir la FAQ
Little Brain
28

En utilisant, ''vous faites de la chaîne. Utilisez sans virgules inversées, cela fonctionnera bien.

iamnotbatma
la source
14
Au début, j'ai ri, puis je lui ai donné une chance qui m'a époustouflé
M au
1
De loin la réponse la plus simple, surtout si le HTML est écrit par vous et dynamique en fonction des entrées de l'utilisateur. Vous pouvez littéralement définir var myHtml = <p> Du texte </p>; et ça marche
pat8719
1
C'est la meilleure réponse. Merci mon pote!
Andy Mercer
3

Pour éviter les erreurs de linter, je l'utilise comme ceci:

  render() {
    const props = {
      dangerouslySetInnerHTML: { __html: '<br/>' },
    };
    return (
        <div {...props}></div>
    );
  }
Tudor Morar
la source
3
import { Fragment } from 'react' // react version > 16.0

var thisIsMyCopy = (
  <Fragment>
    <p>copy copy copy&nbsp;
    <strong>strong copy</strong>
    </p>
  </Fragment>
)

En utilisant '', la valeur est définie sur une chaîne et React n'a aucun moyen de savoir qu'il s'agit d'un élément HTML. Vous pouvez faire ce qui suit pour faire savoir à React qu'il s'agit d'un élément HTML -

  1. Retirez le ''et cela fonctionnerait
  2. Utilisez <Fragment>pour renvoyer un élément HTML.
Amandeep Singh Ghai
la source
2
Cela ne répond pas à la question. Le contenu de thisIsMyCopylui-même est JSX, pas une chaîne de HTML. Vous collez donc JSX dans JSX.
Antares42
Vous pouvez également trouver des fragments dans le pré-acte, mais uniquement dans la version X et les versions ultérieures.
Nasia Makrygianni
-3

Si quelqu'un d'autre atterrit encore ici. Avec ES6, vous pouvez créer votre variable html comme ceci:

render(){
    var thisIsMyCopy = (
        <p>copy copy copy <strong>strong copy</strong></p>
    );
    return(
        <div>
            {thisIsMyCopy}
        </div>
    )
}
Harry
la source
2
et si vous voulez des variables à l'intérieur de votre chaîne, vous devrez envelopper chacune {}et la chaîne entière dans un balisage comme ça(<span>{telephoneNumber} <br /> {email}</span>)
DanV
2
C'est différent de ce qui est demandé dans la question. Dans la question <p>copy copy copy <strong>strong copy</strong></p>est une chaîne. Vous l'avez en tant que JSX.
YPCrumble
4
Ce n'est pas ES6, mais JSX
gztomas
-3

Vous pouvez également inclure ce code HTML dans ReactDOM comme ceci:

var thisIsMyCopy = (<p>copy copy copy <strong>strong copy</strong></p>);

ReactDOM.render(<div className="content">{thisIsMyCopy}</div>, document.getElementById('app'));

Voici deux liens link et link2 de la documentation React qui pourraient être utiles.

Prairie
la source