HTML dizesini React bileşeninde gerçek HTML olarak işleme


182

İşte denediğim ve nasıl ters gittiği.

Bu çalışıyor:

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

Bu değil:

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

Description özelliği, normal bir HTML içeriği dizesidir. Bununla birlikte, bazı nedenlerden dolayı HTML olarak değil, bir dize olarak oluşturulur.

görüntü açıklamasını buraya girin

Herhangi bir öneri?

Yanıtlar:


60

Düğüme eklemeye çalıştığınız metnin şu şekilde çıkıp çıkmadığını kontrol edin:

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

Bunun yerine:

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

eğer kaçtıysa, onu sunucu tarafınızdan dönüştürmelisiniz.

Düğüm metindir çünkü çıkış karakterlidir

Düğüm metindir çünkü çıkış karakterlidir

Düğüm bir dom düğümüdür çünkü çıkış yapılmamıştır

Düğüm bir dom düğümüdür çünkü çıkış yapılmamıştır


3
Sorun buydu. Açıklama dizesi HTML çıkışlıydı. Kaçmadım ve şimdi iyi çalışıyor.
Sergio Tapia

4
Lütfen dangerouslySetInnerHTMLbunun yerine kullanmaktan kaçının Fragmentreact v16. @ Brad-adams ile bir sonraki yanıtı kontrol edin
Kunal Parekh

4
@KunalParekh'in sözünü takdir edin, ancak bunlar farklı şeyler. Cevabım yalnızca html uygulamanızda bulunuyorsa geçerlidir (yani aslında JSX'tir). HTML'yi harici bir kaynaktan jsx'e ayrıştırmak için başka bir çözüm aramanız gerekir.
Brad Adams

125

this.props.match.descriptionbir dize veya bir nesne? Bir dizeyse, HTML'ye dönüştürülmelidir. Misal:

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

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

Bununla birlikte, açıklama <h1 style="color:red;">something</h1>tırnaksız ise '', şunları elde edeceksiniz:

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

Bu bir dizeyse ve herhangi bir HTML biçimlendirmesi görmüyorsanız, gördüğüm tek sorun yanlış biçimlendirmedir ..

GÜNCELLEME

HTML Varlıkları ile uğraşıyorsanız, göndermeden önce bunların kodunu çözmeniz gerekir dangerouslySetInnerHTML, bu yüzden buna "tehlikeli" denir :)

Çalışma örneği:

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.descriptionbir dizedir, nesne değildir. Yanlış işaretlemeyle ne demek istiyorsun? Kapatılmamış etiketleri mi kastediyorsunuz? React onu hayır mı yapmalı?
Sergio Tapia

Buraya console.log (this.props.match.description) yapıştırabilir misiniz;
Ilanus

Bir örnek:&lt;p&gt;&lt;strong&gt;Our Opportunity:&lt;/strong&gt;&lt;/p&gt;
Sergio Tapia

Bu durumda ya .innerHTML kullanmanız ya da HTMLEntities'in kodunu çözmeniz gerekir.
Ilanus

Etiketli birden çok satır veya HTML kodu döndür: function htmlDecode (input) {var e = document.createElement ('div'); e.innerHTML = girdi; var returnString = ''; for (index = 0; index <e.childNodes.length; index ++) {// sadece bir dizge durumu if (e.childNodes [index] .nodeValue) {returnString + = e.childNodes [index] .nodeValue; } // HTML durumu if (e.childNodes [dizin] .outerHTML) {returnString + = e.childNodes [dizin] .outerHTML; }} return returnString; }
Chris Adams

73

'React-html-parser' kullanıyorum

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

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

Npmjs.com'daki kaynak

Daha fazla görünürlük için @ okram'ın yorumunu kaldırma:

github tanımından: HTML dizelerini doğrudan React bileşenlerine dönüştürerek, npmjs.com'dan tehlikeli bir şekilde SetInnerHTML kullanma ihtiyacını ortadan kaldırır HTML dizelerini React bileşenlerine dönüştürmek için bir yardımcı program. DangerouslySetInnerHTML kullanımından kaçınır ve standart HTML öğelerini, niteliklerini ve satır içi stilleri React eşdeğerlerine dönüştürür.


11
Bu kitaplık arka planda "dangerouslySetInnerHTML" kullanıyor mu?
Omar

4
github açıklamasından: Converts HTML strings directly into React components avoiding the need to use dangerouslySetInnerHTMLnpmjs.com'danA 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

Sorunun gerçek yanıtı bu olmalıdır. Yine de teşekkürler.
Stephane

17

Html içeren dizenin nereden geldiği üzerinde kontrole sahipseniz (yani, uygulamanızın herhangi bir yerinde), yeni <Fragment>API'den aşağıdaki gibi bir şey yaparak yararlanabilirsiniz :

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

12
Örneğinizde html içeren bir dize yok. Ya jsx ya da düz dizedir.
mrkvon

3
Eh, evet teknik olarak haklısınız @mrkvon, ancak bahsettiğim gibi, bu çözüm yalnızca "html" / jsx sizin kontrolünüzde olan bir şeyse geçerlidir. Örneğin, bir API aracılığıyla sağlanan bazı ham html'leri oluşturmak için değil . FragmentAPI'den önce benim için her zaman bir acıdı, bu da ekspan sıkıntıydı, bu bazen esnek düzenlerle uğraşan sarımlar . Muhtemel bir çözüm arayan bu soruya tökezledi zaman nasıl paylaşmak istedim ben şeyler yayılmış.
Brad Adams

2
Teşekkürler! Bu benim durumumda işe yarayan tek çözümdü. Ayrıca, bu cevapla ilgili mrkvon'un yorumuna cevap vermek: Bu cevap gerçekten html Some text <strong>wrapped with strong</strong>içerir , yani html etiketi içerir strong.
Binita Bharati

@BinitaBharati Ama bu bir dizi değil. "<p> Bu bir Dize </p>" gibi bir API'den bir dize alırsanız (veya bir dizeyi bir değişkende saklarsanız), bu dizeyi <Fragment> içine koyduğunuzda, çıktı yine de < p> etiketi.
Muchdecal

1
@BradAdams. Yine de güzel numara. Kullanışlı hale geldiği örnekleri görebiliyorum.
Muchdecal


7

dangerouslySetInnerHTML

hazardouslySetInnerHTML, tarayıcı DOM'da innerHTML'yi kullanmak için React'in yerini alıyor. Genel olarak, HTML'yi koddan ayarlamak risklidir çünkü kullanıcılarınızı yanlışlıkla siteler arası komut dosyası çalıştırma (XSS) saldırısına maruz bırakmak kolaydır. Dolayısıyla, HTML'yi doğrudan React'ten ayarlayabilirsiniz, ancak tehlikeli olduğunu kendinize hatırlatmak için, hazardouslySetInnerHTML yazmanız ve __html anahtarıyla bir nesneyi iletmeniz gerekir. Örneğin:

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

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

5

İç HTML'yi aşağıdakileri kapsayacak şekilde birlikte kullanıyorum:

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

Bunu beğendim, bu lüksün olmadığı zamanlarda ek kitaplıklara veya sunucu tarafına güvenmeye gerek yok. Senden ilham aldım, ama yaptığım bir sınıf bileşeninde componentDidMount() { this.message.current.innerHTML = this.state.selectedMessage.body; }body benim için kaçan html oldu.
webhound

3

Benim durumumda react-render-html kullandım

Önce paketi şu şekilde kurun: npm i --save react-render-html

sonra,

import renderHTML from 'react-render-html';

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

3

Bir dizede HTML'niz varsa, adlı bir paketi kullanmanızı tavsiye ederim html-react-parser.

Yükle: npm install html-react-parser veya iplik kullanıyorsanız,yarn add html-react-parser

Bunun gibi bir şey kullanın

import parse from 'html-react-parser'
const yourHtmlString = '<h1>Hello</h1>'
<div>
    {parse(yourHtmlString)}
</div>

Referans: https://www.npmjs.com/package/html-react-parser


1

Ben alamadım npm buildile işe react-html-parser. Ancak benim durumumda https://reactjs.org/docs/fragments.html'yi başarıyla kullanabildim . Birkaç html unicode karakteri gösterme zorunluluğum vardı, ancak bunlar doğrudan JSX'e gömülmemelidir. JSX içinde, Bileşenin durumundan seçilmesi gerekiyordu. Bileşen kod pasajı aşağıda verilmiştir:

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

0

i kullanmak https://www.npmjs.com/package/html-to-react

const HtmlToReactParser = require('html-to-react').Parser;
let htmlInput = html.template;
let htmlToReactParser = new HtmlToReactParser();
let reactElement = htmlToReactParser.parse(htmlInput); 
return(<div>{reactElement}</div>)

-2

{This.props.match.description} üzerinde denetiminiz varsa ve JSX kullanıyorsanız. "DangerouslySetInnerHTML" kullanmamanızı tavsiye ederim.

// 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}
);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.