Reactjs के साथ कच्चे HTML का प्रतिपादन


154

तो क्या यह केवल कच्चे html को अभिकर्मकों के साथ प्रस्तुत करने का एकमात्र तरीका है?

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

मुझे पता है कि JSX के साथ सामान को चिह्नित करने के कुछ शांत तरीके हैं, लेकिन मैं मुख्य रूप से कच्चे html (सभी वर्गों, इनलाइन शैलियों, आदि के साथ) को प्रस्तुत करने में सक्षम हूं। कुछ इस तरह से जटिल:

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

मैं JSX में उस सब को फिर से लिखना नहीं चाहता।

शायद मैं इस सब के बारे में गलत सोच रहा हूं। कृप्या मुझे सही करें।


1
वह लगभग JSX है। यदि आप कच्चे HTML के रूप में बहुत सारे मार्कअप प्रस्तुत करते हैं, तो आप रिएक्ट जैसी लाइब्रेरी का उपयोग करने का लाभ खो रहे हैं। मैं छोटे बदलाव करने की सलाह दूंगा (जैसे "वर्ग" -> "क्लासनेम") रिएक्ट को तत्वों को संभालने देने के लिए।
रॉस एलन

2
इस विशिष्ट उदाहरण के लिए किसी ने पहले से ही आपके लिए काम किया है , हालांकि सवाल अभी भी सामान्य मामले के लिए खड़ा है।
रैंडी मॉरिस

जवाबों:


43

आप html-to-reactnpm मॉड्यूल का लाभ उठा सकते हैं ।

नोट: मैं मॉड्यूल का लेखक हूं और अभी कुछ घंटे पहले प्रकाशित किया है। कृपया किसी भी बग या प्रयोज्य मुद्दों की रिपोर्ट करने के लिए स्वतंत्र महसूस करें।


24
क्या यह आंतरिक रूप से खतरनाक रूप से InnerHTML का उपयोग करता है?
यश शर्मा

2
मैंने अभी कोड चेक किया है। ऐसा लगता है कि यह खतरनाक तरीके से उपयोग नहीं किया गया है। HTML।
अजय राघव

माइक क्या आप अभी भी सक्रिय रूप से इस npm मॉड्यूल को बनाए रख रहे हैं?
डैनियल

हे डैनियल, मैं नहीं है और योगदानकर्ताओं में से एक ने इसे ले लिया और 7 महीने पहले अंतिम रिलीज प्रकाशित किया। देखिए github.com/aknuds1/html-to-react
माइक निकल्स

यह किसी भी खतरनाकSetInnerHTML का उपयोग नहीं करता है।
Tessaracter

185

HTML रेंडर करने के लिए अब सुरक्षित तरीके हैं। मैंने इसे पिछले उत्तर में यहां कवर किया था । आपके पास 4 विकल्प हैं, अंतिम उपयोगdangerouslySetInnerHTML

HTML रेंडर करने के तरीके

  1. सबसे आसान - यूनिकोड का उपयोग करें, फ़ाइल को UTF-8 के रूप में सहेजें और UTF-8 पर सेट करें charset

    <div>{'First · Second'}</div>

  2. सुरक्षित - एक जावास्क्रिप्ट स्ट्रिंग के अंदर इकाई के लिए यूनिकोड संख्या का उपयोग करें।

    <div>{'First \u00b7 Second'}</div>

    या

    <div>{'First ' + String.fromCharCode(183) + ' Second'}</div>

  3. या तार और JSX तत्वों के साथ मिश्रित सरणी।

    <div>{['First ', <span>&middot;</span>, ' Second']}</div>

  4. अंतिम रिज़ॉर्ट - का उपयोग करके कच्चे HTML डालें dangerouslySetInnerHTML

    <div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />


मुझे केवल 3 या 4 की आवश्यकता है
निकोलस एसएक्सयू

सोच रहा था कि dangerouslySetInnerHTML__एचटीएमएल के अलावा और कौन-कौन से गुण हैं
जुआन सोलानो

30
मैं इन धागे से प्यार करता हूँ ... स्पष्ट रूप से: "जो कुछ भी आप # 4 का उपयोग नहीं कर सकते हैं वह करें"। हर कोई: "# 4 महान काम किया!"
गहरायाल

1
@JuanSolano कोई नहीं, टाइपस्क्रिप्ट वातावरण में स्वतः पूर्ण प्रविष्टियों के अनुसार।
एंड्रियास लिनर्ट

इसी तरह के प्रश्न में, stackoverflow.com/questions/19266197/… , यह उत्तर बहुत अच्छा नहीं था। शायद यह इस सवाल के लिए बेहतर है या शायद लोग जवाब नहीं पढ़ रहे हैं ...: D
425nesp

27

मैंने इसका उपयोग त्वरित और गंदे परिस्थितियों में किया है:

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

7
यह सुरक्षित नहीं है - यदि HTML में <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="alert('test');">क्या है?
यजॉन्ग

11
यदि आप HTML के नियंत्रण में हैं तो यह सुरक्षित है
John

18

मैंने इस शुद्ध घटक की कोशिश की है:

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

विशेषताएं

  • classNameसहारा लेता है (इसे स्टाइल करना आसान है)
  • के स्थान पर \nकरने के लिए <br />(आप अक्सर कि क्या करना चाहते हैं)
  • अवयव का उपयोग करते समय सामग्री बच्चों की तरह रखें:
  • <RawHTML>{myHTML}</RawHTML>

मैंने घटक को जीआईटीबी: रॉबॉट : जीएटीएमटी: रिएक्टजस शुद्ध घटक में HTML को प्रस्तुत करने के लिए रखा है


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

मेरे लिए उपर्युक्त कार्य, मैं html को मोडल बॉडी में दे रहा था।
जोजकर

12

खतरनाक डोम ब्राउज़र में आंतरिक HTML का उपयोग करने के लिए React की प्रतिक्रिया रिएक्ट का प्रतिस्थापन है। सामान्य तौर पर, HTML को कोड से सेट करना जोखिम भरा होता है क्योंकि अनजाने में अपने उपयोगकर्ताओं को क्रॉस-साइट स्क्रिप्टिंग (XSS) हमले के लिए उजागर करना आसान होता है।

अपने कच्चे HTML (जैसे, DOMPurify का उपयोग करके) को DOM के माध्यम से इंजेक्ट करने से पहले उसे सुरक्षित करना बेहतर / सुरक्षित है dangerouslySetInnerHTML

DOMPurify - HTML, MathML और SVG के लिए एक DOM-only, सुपर-फास्ट, uber-tolerant XSS सैनिटाइज़र। DOMPurify एक सुरक्षित डिफ़ॉल्ट के साथ काम करता है, लेकिन बहुत अधिक विन्यास और हुक प्रदान करता है।

उदाहरण :

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

यह वही है जो मैं इस जवाब में ढूंढ रहा था। यह अधिक
अपवित्र

6

मैंने पार्सर नामक इस पुस्तकालय का उपयोग किया । इसने जो मुझे चाहिए था उसके लिए काम किया।

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

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

3
21KB (8KB gzipped)। मैं ब्राउज़र कोड के लिए इसे सही नहीं ठहरा सकता।
पीटर बेंग्सटन

यह लाइब्रेरी मेरे एक्सपो ऐप को
तोड़ती है

5

dangerouslySetInnerHTMLजब तक बिल्कुल आवश्यक नहीं किया जाना चाहिए। डॉक्स के अनुसार, "यह मुख्य रूप से DOM स्ट्रिंग हेरफेर लाइब्रेरी के साथ सहयोग करने के लिए है" । जब आप इसका उपयोग करते हैं, तो आप प्रतिक्रिया के DOM प्रबंधन का लाभ दे रहे हैं।

आपके मामले में, वैध JSX सिंटैक्स में कनवर्ट करना बहुत सरल है; सिर्फ classविशेषताओं को बदलें className। या, जैसा कि ऊपर टिप्पणी में कहा गया है, आप ReactBootstrap लाइब्रेरी का उपयोग कर सकते हैं जो बूटस्ट्रैप तत्वों को प्रतिक्रिया घटकों में एन्क्रिप्ट करता है।


8
आपके उत्तर के लिए धन्यवाद। मैं आंतरिक HTML का उपयोग करने के सुरक्षा निहितार्थ को समझता हूं और मुझे पता है कि मैं इसे JSX में बदल सकता हूं। लेकिन मैं विशेष रूप से कच्चे HTML स्निपेट के उपयोग के लिए रिएक्ट के समर्थन के बारे में पूछ रहा हूं।
विन्होबे

"कच्चे HTML स्निपेट्स का उपयोग करने के लिए प्रतिक्रिया का समर्थन" से वास्तव में आपका क्या अभिप्राय है?
ब्रेनो फेरेरा

2

यहां पहले से पोस्ट किए गए RawHTML फ़ंक्शन का थोड़ा कम राय वाला संस्करण है। यह आपको देता है:

  • टैग को कॉन्फ़िगर करें
  • वैकल्पिक रूप से की जगह नई-पंक्तियों के लिए <br />की
  • अतिरिक्त प्रॉप्स पास करें जो रॉ-HTML बनाए गए तत्व को पास करेगा
  • एक खाली तार की आपूर्ति ( RawHTML></RawHTML>)

यहाँ घटक है:

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

उपयोग:

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

आउटपुट:

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

इस पर टूट जाएगा:

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

0

मुझे अपने सिर में onLoad विशेषता के साथ एक लिंक का उपयोग करने की आवश्यकता थी जहां div की अनुमति नहीं है, इसलिए इससे मुझे महत्वपूर्ण दर्द हुआ। मेरा वर्तमान समाधान मूल स्क्रिप्ट टैग को बंद करना है, मुझे जो करना है, उसे करें, फिर स्क्रिप्ट टैग खोलें (मूल द्वारा बंद किया जाए)। आशा है कि यह किसी ऐसे व्यक्ति की मदद कर सकता है जिसके पास कोई अन्य विकल्प नहीं है:

<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>`,}}/>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.