Wstaw HTML za pomocą instrukcji React Variable (JSX)

203

Tworzę coś z React, gdzie muszę wstawić HTML z React Variables w JSX. Czy istnieje sposób na taką zmienną:

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

i wstawić go w taki sposób, żeby działał?

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

i czy wstawia HTML zgodnie z oczekiwaniami? Nie widziałem ani nie słyszałem nic na temat funkcji reagowania, która mogłaby to zrobić bezpośrednio, lub metody analizowania rzeczy, które pozwoliłyby na to.

Kyle Hotchkiss
źródło

Odpowiedzi:

294

Możesz użyć niebezpiecznieSetInnerHTML , np

render: function() {
    return (
        <div className="content" dangerouslySetInnerHTML={{__html: thisIsMyCopy}}></div>
    );
}
Douglas
źródło
2
Jak to działa, jeśli musisz coś dodać <head>?
Danielle Madeley
Normalne metody DOM w componentDidMount powinny działać, ale nie robiłem tego wcześniej.
Douglas,
@DanielleMadeley Czy próbujesz wstawić warunkowe komentarze IE do <head>? Jeśli tak, odniosłem
Cam Jackson
3
Upewnij się, że przekazujesz metodę do niebezpiecznieSetInnerHTML, a nie skrótu. Według doktorów przechodzenie skrótu jest niebezpieczne. Odniesienie: facebook.github.io/react/tips/dangerously-set-inner-html.html
krytyk
1
Czy istnieje sposób bez wstawiania div?
koleś
101

Pamiętaj, że dangerouslySetInnerHTMLmoże być niebezpieczne, jeśli nie wiesz, co zawiera wstrzykiwany ciąg HTML. Wynika to z tego, że złośliwy kod po stronie klienta można wstrzykiwać za pomocą znaczników skryptu.

Prawdopodobnie dobrym pomysłem jest odkażenie łańcucha HTML za pomocą narzędzia takiego jak DOMPurify, jeśli nie masz 100% pewności, że renderowany HTML jest bezpieczny dla XSS (cross-site scripting).

Przykład:

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
źródło
@vsync nie, nie powinno :)
Artem Bernatskyi
1
czy możliwe jest renderowanie nie tylko znaczników HTML, ale także znaczników z biblioteki, takich jak znacznik alertów interfejsu użytkownika? chcę, żeby kod był takiimport 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, Czy masz jakieś rozwiązanie dla tego scenariusza?
Nimish goel
51

niebezpiecznieSetInnerHTML ma wiele wad, ponieważ znajduje się wewnątrz znacznika.

Sugeruję, abyś użył do tego jakiegoś reagującego opakowania, jak znalazłem tutaj na npm. parser HTML-Reaktywuj wykonuje tę samą pracę.

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

Bardzo prosty :)

użytkownik2903536
źródło
3
„NiebezpiecznieSetInnerHTML ma wiele wad, ponieważ znajduje się wewnątrz znacznika.” Czy możesz wyjaśnić więcej na ten temat. Próbuję się zastanowić, jaka jest zasadnicza różnica między analizatorem składni HTML-sanatorizowanym a sanatized innerHtml
dchhetri
Wygląda na to, że html-reaktor-parser nie dezynfekuje danych wejściowych - zobacz FAQ
Little Brain
28

Za pomocą ''robisz to na sznurku. Użyj bez odwróconych przecinków, będzie działać dobrze.

iamnotbatma
źródło
14
Najpierw się roześmiałem, a potem dałem mu szansę, która oszalała
M na
1
Zdecydowanie najprostsza odpowiedź, zwłaszcza jeśli HTML jest napisany przez Ciebie i dynamiczny na podstawie danych wprowadzonych przez użytkownika. Możesz dosłownie ustawić var ​​myHtml = <p> Trochę tekstu </p>; i działa
pat8719
1
To najlepsza odpowiedź. Dzięki stary!
Andy Mercer
3

Aby uniknąć błędów linijek, używam go w następujący sposób:

  render() {
    const props = {
      dangerouslySetInnerHTML: { __html: '<br/>' },
    };
    return (
        <div {...props}></div>
    );
  }
Tudor Morar
źródło
3
import { Fragment } from 'react' // react version > 16.0

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

Używając „” ustawia wartość na ciąg znaków, a React nie ma możliwości dowiedzenia się, że jest to element HTML. Możesz wykonać następujące czynności, aby poinformować React, że jest to element HTML -

  1. Usuń ''i to by działało
  2. Użyj, <Fragment>aby zwrócić element HTML.
Amandeep Singh Ghai
źródło
2
To nie odpowiada na pytanie. Treść thisIsMyCopysama w sobie to JSX, a nie ciąg HTML. Więc dosłownie wklejasz JSX do JSX.
Antares42
Fragmenty można także znaleźć w Preact, ale tylko w wersji X i późniejszych.
Nasia Makrygianni
-3

Jeśli ktoś jeszcze tu wyląduje. Za pomocą ES6 możesz utworzyć swoją zmienną HTML tak:

render(){
    var thisIsMyCopy = (
        <p>copy copy copy <strong>strong copy</strong></p>
    );
    return(
        <div>
            {thisIsMyCopy}
        </div>
    )
}
Złupić
źródło
2
a jeśli chcesz mieć zmienne w swoim łańcuchu, musisz zawinąć każdy {}i cały łańcuch w taki sposób(<span>{telephoneNumber} <br /> {email}</span>)
DanV
2
Różni się to od pytania zadanego w pytaniu. W pytaniu <p>copy copy copy <strong>strong copy</strong></p>jest ciąg. Masz go jako JSX.
YPCrumble,
4
To nie jest ES6, ale JSX
gztomas
-3

Możesz także dołączyć ten kod HTML do ReactDOM w następujący sposób:

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

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

Oto dwa linki link i link2 z dokumentacji React, które mogą być pomocne.

Łąka
źródło