web-dev-qa-db-fra.com

Rendu du HTML brut avec reactjs

Alors est-ce la seule façon de rendre du HTML brut avec reactjs?

// http://facebook.github.io/react/docs/tutorial.html
// tutorial7.js
var converter = new Showdown.converter();
var Comment = React.createClass({
  render: function() {
    var rawMarkup = converter.makeHtml(this.props.children.toString());
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        <span dangerouslySetInnerHTML={{__html: rawMarkup}} />
      </div>
    );
  }
});

Je sais qu'il y a de bonnes façons de baliser des choses avec JSX, mais je suis surtout intéressé à pouvoir rendre du HTML brut (avec toutes les classes, styles en ligne, etc.). Quelque chose de compliqué comme ça:

<!-- http://getbootstrap.com/components/#dropdowns-example -->
<div class="dropdown">
  <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
    Dropdown
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
  </ul>
</div>

Je ne voudrais pas avoir à réécrire tout cela dans JSX.

Peut-être que je pense à tout cela est faux. S'il vous plaît corrigez-moi.

98
vinhboy

Vous pouvez utiliser le module html-to-react npm à l’adresse https://www.npmjs.com/package/html-to-react .

Remarque: je suis l'auteur du module et je viens de le publier il y a quelques heures. N'hésitez pas à signaler tout bogue ou problème d'utilisation.

28
Mike Nikles

J'ai utilisé cela dans des situations rapides et sales:

// react render method:

render() {
    return (
      <div>
        { this.props.textOrHtml.indexOf('</') !== -1
            ? (
                <div dangerouslySetInnerHTML={{__html: this.props.textOrHtml.replace(/(<? *script)/gi, 'illegalscript')}} >
                </div>
              )
            : this.props.textOrHtml
          }

      </div>
      )
  }
18
Cory Robinson
export class ModalBody extends Component{
    rawMarkup(){
        var rawMarkup = this.props.content
        return { __html: rawMarkup };
    }
    render(){
        return(
                <div className="modal-body">
                     <span dangerouslySetInnerHTML={this.rawMarkup()} />

                </div>
            )
    }
}
10
Jozcar

J'ai essayé ce composant pur:

const RawHTML = ({children, className = ""}) => 
<div className={className}
  dangerouslySetInnerHTML={{ __html: children.replace(/\n/g, '<br />')}} />

Caractéristiques 

  • Prend classNameprop (plus facile à dénommer)
  • Remplace \n par <br /> (vous voulez souvent le faire)
  • Placez le contenu sous la forme (enfants} _ lorsque vous utilisez le composant comme 
  • <RawHTML>{myHTML}</RawHTML>

J'ai placé le composant dans un Gist sur Github: RawHTML: Composant pur ReactJS pour le rendu HTML

10
Netsi1964

dangerouslySetInnerHTML ne doit pas être utilisé sauf en cas d'absolue nécessité. Selon la documentation, "C’est principalement pour coopérer avec les bibliothèques de manipulation de chaînes DOM" . Lorsque vous l'utilisez, vous renoncez aux avantages de la gestion DOM de React.

Dans votre cas, il est assez simple de convertir à la syntaxe valide JSX, il suffit de changer les attributs class en className. Ou, comme mentionné dans les commentaires ci-dessus, vous pouvez utiliser la bibliothèque ReactBootstrap qui encapsule les éléments Bootstrap dans des composants React.

4
Breno Ferreira

J'ai utilisé cette bibliothèque appelée Parser, elle a fonctionné pour ce dont j'avais besoin.

https://github.com/remarkablemark/html-react-parser

import React, { Component } from 'react';    
import Parser from 'html-react-parser';

class MyComponent extends Component {
  render() {
    <div>{Parser(this.state.message)}</div>
  }
};
2
ecairol

dangereusementSetInnerHTML est le remplacement par React de l’utilisation de innerHTML dans le DOM du navigateur. En général, définir du code HTML à partir de code est risqué, car il est facile d’exposer par inadvertance vos utilisateurs à une attaque XSS (cross-site scripting).

Il est préférable/plus sûr d'assainir votre code HTML brut (à l'aide de DOMPurify, par exemple) avant de l'injecter dans le DOM via dangerouslySetInnerHTML.

DOMPurify - un assainisseur XSS ultra-tolérant et ultra-tolérant pour HTML, MathML et SVG. DOMPurify fonctionne avec une valeur par défaut sécurisée, mais offre beaucoup de configurabilité et de points d'ancrage.

Exemple :

import React from 'react'
import createDOMPurify from 'dompurify'
import { JSDOM } from 'jsdom'

const window = (new JSDOM('')).window
const DOMPurify = createDOMPurify(window)

const rawHTML = `
<div class="dropdown">
  <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
    Dropdown
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
  </ul>
</div>
`

const YourComponent = () => (
  <div>
    { <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(rawHTML) }} /> }
  </div>
)

export default YourComponent
1
Yuci

Voici une version un peu moins avisée de la fonction RawHTML postée auparavant. Cela vous permet:

  • configurer le tag
  • éventuellement remplacer les nouvelles lignes par <br /> '
  • transmettre des accessoires supplémentaires que RawHTML transmettra à l'élément créé
  • fournir une chaîne vide (RawHTML></RawHTML>)

Voici le composant:

const RawHTML = ({ children, tag = 'div', nl2br = true, ...rest }) =>
    React.createElement(tag, {
        dangerouslySetInnerHTML: {
            __html: nl2br
                ? children && children.replace(/\n/g, '<br />')
                : children,
        },
        ...rest,
    });
RawHTML.propTypes = {
    children: PropTypes.string,
    nl2br: PropTypes.bool,
    tag: PropTypes.string,
};

Usage:

<RawHTML>{'First &middot; Second'}</RawHTML>
<RawHTML tag="h2">{'First &middot; Second'}</RawHTML>
<RawHTML tag="h2" className="test">{'First &middot; Second'}</RawHTML>
<RawHTML>{'first line\nsecond line'}</RawHTML>
<RawHTML nl2br={false}>{'first line\nsecond line'}</RawHTML>
<RawHTML></RawHTML>

Sortie:

<div>First · Second</div>
<h2>First · Second</h2>
<h2 class="test">First · Second</h2>
<div>first line<br>second line</div>
<div>first line
second line</div>
<div></div>

Ça va casser le:

<RawHTML><h1>First &middot; Second</h1></RawHTML>
1

J'avais besoin d'utiliser un lien avec l'attribut onLoad dans ma tête où div n'est pas autorisé, donc cela m'a causé une douleur importante. Ma solution actuelle consiste à fermer la balise de script d'origine, à faire ce que je dois faire, puis à ouvrir la balise de script (à fermer par l'original). J'espère que cela pourra aider quelqu'un qui n'a pas d'autre choix: 

<script dangerouslySetInnerHTML={{ __html: `</script>
   <link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans" as="style" onLoad="this.onload=null;this.rel='stylesheet'" crossOrigin="anonymous"/>
<script>`,}}/>
0
Adam Lane