Jadikan string HTML sebagai HTML asli dalam komponen Bereaksi


162

Inilah yang saya coba dan bagaimana kesalahannya.

Ini bekerja:

<div dangerouslySetInnerHTML={{ __html: "<h1>Hi there!</h1>" }} />

Ini tidak:

<div dangerouslySetInnerHTML={{ __html: this.props.match.description }} />

Properti deskripsi hanyalah string normal konten HTML. Namun itu diterjemahkan sebagai string, bukan sebagai HTML karena alasan tertentu.

masukkan deskripsi gambar di sini

Ada saran?

Jawaban:


51

Periksa apakah teks yang Anda coba tambahkan ke node tidak lolos seperti ini:

var prop = {
    match: {
        description: '&lt;h1&gt;Hi there!&lt;/h1&gt;'
    }
};

Alih-alih ini:

var prop = {
    match: {
        description: '<h1>Hi there!</h1>'
    }
};

jika lolos Anda harus mengubahnya dari sisi server Anda.

Node adalah teks karena lolos

Node adalah teks karena lolos

Node adalah dom dom karena tidak lolos

Node adalah dom dom karena tidak lolos


3
Ini masalahnya. String deskripsi diloloskan dari HTML. Saya melepaskannya dan sekarang berfungsi dengan baik.
Sergio Tapia

4
Harap hindari menggunakan dangerouslySetInnerHTMLalih - alih menggunakan Fragmentdari react v16. Periksa jawaban berikutnya oleh @ brad-adams
Kunal Parekh

2
Menghargai menyebutkan @KunalParekh, tetapi mereka hal yang berbeda. Jawaban saya hanya valid jika html terletak di dalam aplikasi Anda (artinya sebenarnya JSX). Untuk mem-parsing HTML dari sumber eksternal ke jsx Anda harus mencari solusi lain.
Brad Adams

113

Apakah this.props.match.descriptionApakah string atau suatu objek? Jika ini sebuah string, itu harus dikonversi ke HTML dengan baik. Contoh:

class App extends React.Component {

constructor() {
    super();
    this.state = {
      description: '<h1 style="color:red;">something</h1>'
    }
  }

  render() {
    return (
      <div dangerouslySetInnerHTML={{ __html: this.state.description }} />
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

Hasil: http://codepen.io/ilanus/pen/QKgoLA?editors=1011

Namun jika description: <h1 style="color:red;">something</h1>tanpa tanda kutip ''Anda akan mendapatkan:

Object {
$$typeof: [object Symbol] {},
  _owner: null,
  key: null,
  props: Object {
    children: "something",
    style: "color:red;"
  },
  ref: null,
  type: "h1"
}

Jika ini sebuah string dan Anda tidak melihat markup HTML, satu-satunya masalah yang saya lihat adalah markup yang salah ..

MEMPERBARUI

Jika Anda berurusan dengan HTMLEntitles. Anda harus memecahkan kode sebelum mengirimnyadangerouslySetInnerHTML itu sebabnya mereka menyebutnya berbahaya :)

Contoh kerja:

class App extends React.Component {

  constructor() {
    super();
    this.state = {
      description: '&lt;p&gt;&lt;strong&gt;Our Opportunity:&lt;/strong&gt;&lt;/p&gt;'
    }
  }

   htmlDecode(input){
    var e = document.createElement('div');
    e.innerHTML = input;
    return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
  }

  render() {
    return (
      <div dangerouslySetInnerHTML={{ __html: this.htmlDecode(this.state.description) }} />
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

this.props.match.descriptionadalah string, bukan objek. Apa yang Anda maksud dengan markup yang salah? Apakah maksud Anda tag tidak tertutup? Bereaksi hanya harus membuatnya tidak?
Sergio Tapia

Bisakah Anda tempel di sini console.log (this.props.match.description);
Ilanus

Salah satu contoh:&lt;p&gt;&lt;strong&gt;Our Opportunity:&lt;/strong&gt;&lt;/p&gt;
Sergio Tapia

Dalam hal ini Anda harus menggunakan .innerHTML atau mendekode HTMLEntities.
Ilanus

Kembalikan beberapa baris atau kode HTML dengan tag: function htmlDecode (input) {var e = document.createElement ('div'); e.innerHTML = input; var returnString = ''; untuk (index = 0; index <e.childNodes.length; index ++) {// kasus hanya string jika (e.childNodes [index] .nodeValue) {returnString + = e.childNodes [index] .nodeValue; } // kasus HTML if (e.childNodes [index] .outerHTML) {returnString + = e.childNodes [index] .outerHTML; }} return returnString; }
Chris Adams

58

Saya menggunakan 'react-html-parser'

yarn add react-html-parser
import ReactHtmlParser from 'react-html-parser'; 

<div> { ReactHtmlParser (html_string) } </div>

Sumber di npmjs.com

Mengangkat komentar @ okram untuk lebih banyak visibilitas:

dari uraian github-nya: Mengubah string HTML secara langsung menjadi komponen Bereaksi, menghindari kebutuhan untuk menggunakan berbahayaSetInnerHTML dari npmjs.com Utilitas untuk mengubah string HTML menjadi komponen Bereaksi. Menghindari penggunaan berbahayaSetInnerHTML dan mengubah elemen HTML standar, atribut dan gaya inline menjadi Bereaksi setara mereka.


11
Apakah perpustakaan ini menggunakan "hazardouslySetInnerHTML" di latar belakang?
Omar

1
dari deskripsi github: Converts HTML strings directly into React components avoiding the need to use dangerouslySetInnerHTMLdari npmjs.comA utility for converting HTML strings into React components. Avoids the use of dangerouslySetInnerHTML and converts standard HTML elements, attributes and inline styles into their React equivalents.
okram

15

Jika Anda memiliki kendali atas dari mana string yang berisi html berasal (mis. Di suatu tempat di aplikasi Anda), Anda dapat mengambil manfaat dari <Fragment>API baru , melakukan sesuatu seperti:

import React, {Fragment} from 'react'

const stringsSomeWithHtml = {
  testOne: (
    <Fragment>
      Some text <strong>wrapped with strong</strong>
    </Fragment>
  ),
  testTwo: `This is just a plain string, but it'll print fine too`,
}

...

render() {
  return <div>{stringsSomeWithHtml[prop.key]}</div>
}

11
Tidak ada string yang berisi html dalam contoh Anda. Entah jsx atau string biasa.
mrkvon

3
Ya, secara teknis Anda benar @ mrkvon, namun seperti yang saya sebutkan, solusi ini hanya valid jika mengatakan "html" / jsx adalah sesuatu yang Anda kendalikan. Tidak untuk merender beberapa html mentah yang disediakan melalui API, misalnya. Sebelum FragmentAPI, itu selalu menyakitkan bagi saya, yang membutuhkan spanpembungkus tambahan yang kadang-kadang mengacaukan tata letak fleksibel. Ketika saya menemukan pertanyaan ini untuk mencari solusi yang mungkin, saya pikir saya akan membagikan bagaimana saya menyelesaikan masalah.
Brad Adams

2
Terima kasih! Ini adalah satu-satunya solusi yang berhasil dalam kasus saya. Juga, menanggapi komentar mrkvon pada jawaban ini: Jawaban ini memang mengandung html yaitu Some text <strong>wrapped with strong</strong>berisi tag html strong.
Binita Bharati

@BinitaBharati Tapi itu bukan string. Jika Anda mendapatkan string dari API seperti "<p> Ini adalah String </p>" (atau hanya menyimpan string dalam variabel), saat Anda meletakkan string ini di <Fragment>, output akan tetap mengandung < p> tag.
Muchdecal

1
@BradAdams. Trik yang bagus. Saya bisa melihat contoh di mana itu menjadi berguna.
Muchdecal


6

berbahayaInetHTML

hazardouslySetInnerHTML adalah pengganti React untuk menggunakan innerHTML di browser DOM. Secara umum, pengaturan HTML dari kode berisiko karena mudah untuk secara tidak sengaja mengekspos pengguna Anda terhadap serangan lintas situs (XSS). Jadi, Anda dapat mengatur HTML langsung dari Bereaksi, tetapi Anda harus mengetikkan berbahayaSetInnerHTML dan meneruskan objek dengan kunci __html, untuk mengingatkan diri sendiri bahwa itu berbahaya. Sebagai contoh:

function createMarkup() {
  return {__html: 'First &middot; Second'};
}

function MyComponent() {
  return <div dangerouslySetInnerHTML={createMarkup()} />;
}

3

Saya menggunakan innerHTML bersama-sama ref untuk span:

import React, { useRef, useEffect, useState } from 'react';

export default function Sample() {
  const spanRef = useRef<HTMLSpanElement>(null);
  const [someHTML,] = useState("some <b>bold</b>");

  useEffect(() => {
    if (spanRef.current) {
      spanRef.current.innerHTML = someHTML;
    }
  }, [spanRef.current, someHTML]);

  return <div>
    my custom text follows<br />
    <span ref={spanRef} />
  </div>
}

Saya suka ini, tidak perlu perpustakaan tambahan atau mengandalkan sisi server ketika Anda tidak memiliki kemewahan itu. Terinspirasi oleh Anda, tetapi dalam komponen kelas yang saya lakukan componentDidMount() { this.message.current.innerHTML = this.state.selectedMessage.body; }tubuh adalah html yang lolos untuk saya.
webhound

2

Dalam kasus saya, saya menggunakan react-render-html

Pertama instal paket dengan npm i --save react-render-html

kemudian,

import renderHTML from 'react-render-html';

renderHTML("<a class='github' href='https://github.com'><b>GitHub</b></a>")

1

Saya tidak bisa mendapatkannya npm build bekerja react-html-parser. Namun, dalam kasus saya, saya berhasil menggunakan https://reactjs.org/docs/fragments.html . Saya memiliki persyaratan untuk menunjukkan beberapa karakter html unicode, tetapi mereka tidak boleh langsung disematkan di JSX. Di dalam BEJ, itu harus dipilih dari status Komponen. Cuplikan kode komponen diberikan di bawah ini:

constructor() 
{
this.state = {
      rankMap : {"5" : <Fragment>&#9733; &#9733; &#9733; &#9733; &#9733;</Fragment> , 
                 "4" : <Fragment>&#9733; &#9733; &#9733; &#9733; &#9734;</Fragment>, 
                 "3" : <Fragment>&#9733; &#9733; &#9733; &#9734; &#9734;</Fragment> , 
                 "2" : <Fragment>&#9733; &#9733; &#9734; &#9734; &#9734;</Fragment>, 
                 "1" : <Fragment>&#9733; &#9734; &#9734; &#9734; &#9734;</Fragment>}
                };
}

render() 
{
       return (<div class="card-footer">
                    <small class="text-muted">{ this.state.rankMap["5"] }</small>
               </div>);
}


-2

Jika Anda memiliki kontrol ke {this.props.match.description} dan jika Anda menggunakan JSX. Saya akan merekomendasikan untuk tidak menggunakan "hazardouslySetInnerHTML".

// In JSX, you can define a html object rather than a string to contain raw HTML
let description = <h1>Hi there!</h1>;

// Here is how you print
return (
    {description}
);
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.