React-如何在道具中传递HTML标签?


118

我希望能够通过HTML标签传递文本,如下所示:

<MyComponent text="This is <strong>not</strong> working." />

但是在MyComponent的render方法中,当我打印出时this.props.text,它实际上打印出了所有内容:

This is <strong>not</strong> working.

有什么方法可以使React解析HTML并将其正确转储吗?


您实际的渲染功能是什么?
Lucio

3
典型的模式是使您的内容成为组件的子代<MyComponent>This is <strong>not</strong> working</MyComponent>,而不是将它们作为道具传递。您能否为您实际想要完成的工作提供更多背景信息?
尼克·汤姆林

几乎相同的问题:Reactjs转换为html
totymedli

Answers:


140

您可以将混合数组与字符串和JSX元素一起使用(请参见此处的文档):

<MyComponent text={["This is ", <strong>not</strong>,  "working."]} />

这里有一个小提琴显示了它的工作原理http : //jsfiddle.net/7s7dee6L/

另外,作为最后的选择,您始终可以插入原始HTML,但是请小心,因为如果不清理属性值,这可能使您容易受到跨站点脚本(XSS)攻击。


10
除我现在收到警告外,此方法有效:警告:数组或迭代器中的每个子代都应具有唯一的“键”道具。检查CTA的渲染方法。它是从Template1传递过来的一个孩子。有关更多信息,请参见fb.me/react-warning-keys
ffxsam 2015年

3
您可以通过遍历数组并将索引添加为MyComponent中的键来消除此错误, {text.map( textOrHTML, index) => <span key={index}>{textOrHTML}</span> )} 尽管这很奇怪,我们必须首先完全执行此操作。
HussienK '16

5
您也可以通过将固定预警key="[some unique value]"<strong>的元素。
乍得·约翰逊

很好,工作正常,我想知道如何在
Strong

2
为了消除数组键警告,现在还可以像这样传递单个JSX。<MyComponent text={<>This is <strong>not</strong> working.</>} />
阿里夫

111

实际上,可以采用多种方法。

您想在道具中使用JSX

您可以简单地使用{}使JSX解析参数。唯一的限制与每个JSX元素相同:它必须仅返回一个根元素。

myProp={<div><SomeComponent>Some String</div>}

最好的可读方法是创建一个函数renderMyProp,该函数将返回JSX组件(就像标准渲染函数一样),然后只需调用myProp = {this.renderMyProp()}

您只想将HTML作为字符串传递

默认情况下,JSX不允许您从字符串值呈现原始HTML。但是,有一种方法可以做到这一点:

myProp="<div>This is some html</div>"

然后可以在组件中像这样使用它:

<div dangerouslySetInnerHTML=myProp={{ __html: this.renderMyProp() }}></div>

请注意,此解决方案可以在跨站点脚本伪造攻击中“打开”。还要注意,您只能呈现简单的HTML,不能呈现JSX标签或组件或其他奇特的东西。

数组方式

作为响应,您可以传递一个JSX元素数组。这意味着:

myProp={["This is html", <span>Some other</span>, "and again some other"]}

我不推荐这种方法,因为:

  • 它将创建一个警告(缺少键)
  • 不可读
  • 这并不是真正的JSX方式,它更像是一种hack,而非预期的设计。

孩子们的方式

为了完整起见添加它,但为了做出反应,您还可以使所有“位于”组件内部的子项。

因此,如果我采用以下代码:

<SomeComponent>
    <div>Some content</div>
    <div>Some content</div>
</SomeComponent>

然后,这两个div将在SomeComponent中以this.props.children的形式提供,并且可以使用标准{}语法进行呈现。

当您只有一个HTML内容要传递给组件时,此解决方案是完美的(想象一个Popin组件仅将Popin的内容作为子组件)。

但是,如果您有多个内容,则不能使用子级(或至少需要将其与此处的其他解决方案结合使用)


1
this.props.childrens-但是this.props.children。没有' s'reactjs.org/docs
glossary.html

13

您可以危险地使用SetInnerHTML

只需将html作为普通字符串发送

<MyComponent text="This is <strong>not</strong> working." />

并在JSX代码中呈现如下:

<h2 className="header-title-right wow fadeInRight"
    dangerouslySetInnerHTML={{__html: props.text}} />

如果要渲染用户输入的数据,请小心。您可能是XSS攻击的受害者

这里是文档:https : //facebook.github.io/react/tips/dangerously-set-inner-html.html


7
<MyComponent text={<span>This is <strong>not</strong> working.</span>} />

然后在您的组件中可以像下面这样进行道具检查:

import React from 'react';
export default class MyComponent extends React.Component {
  static get propTypes() {
    return {
      text: React.PropTypes.object, // if you always want react components
      text: React.PropTypes.any, // if you want both text or react components
    }
  }
}

确保仅选择一种道具类型。


6

对我来说,它通过在道具儿童中传递html标签而起作用

<MyComponent>This is <strong>not</strong> working.</MyComponent>


var MyComponent = React.createClass({

   render: function() {
    return (
      <div>this.props.children</div>
    );
   },


6

在客户端的React应用程序上,有几种方法可以将prop呈现为带有某些html的字符串。一个比另一个更安全...

1-将prop定义为jsx(我的偏好)

const someProps = {
  greeting: {<div>Hello<a href="/${name_profile}">${name_profile}</a></div>}
}


const GreetingComopnent = props => (
  <p>{props.someProps.greeting}</p>
)

•这里唯一的要求是,无论生成该道具的任何文件都需要包含React作为依赖项(以防在辅助文件中生成道具的jsx等)。

2-危险地设置innerHtml

const someProps = {
  greeting: '<React.Fragment>Hello<a href="https://stackoverflow.com/${name_profile}">${name_profile}</a></React.Fragment>'
}

const GreetingComponent = props => {
  const innerHtml = { __html: props.someProps.greeting }
  return <p dangerouslySetInnerHtml={innerHtml}></p>
}

•不建议使用第二种方法。想象一下一个输入字段,其输入值在此组件中作为prop呈现。用户可以在输入中输入脚本标签,而呈现此输入的组件将执行此潜在的恶意代码。因此,这种方法有可能引入跨站点脚本漏洞。有关更多信息,请参考官方的React文档。



3

您可以通过我所知道的2种方式来做到这一点。

1- <MyComponent text={<p>This is <strong>not</strong> working.</p>} />

然后做

class MyComponent extends React.Component {
   render () {
     return (<div>{this.props.text}</div>)
   }
}

或者第二种方法是这样

2 <MyComponent><p>This is <strong>not</strong> working.</p><MyComponent/>

然后做

class MyComponent extends React.Component {
   render () {
     return (<div>{this.props.children}</div>)
   }
}

1
我添加了一个变量let vhtml = "<p>Test</p>"并像这样在prop上使用了它,由于text={vhtml}某种原因,它仍然以纯文本形式呈现。
8

2

@matagus的答案对我来说很好,摘录下面的希望对那些希望在其中使用变量的人有所帮助。

const myVar = 'not';
<MyComponent text={["This is ", <strong>{`${myVar}`}</strong>,  "working."]} />

1

在我的项目中,我必须传递来自变量的动态html代码段并将其呈现在组件内部。所以我做了以下。

defaultSelection : {
    innerHtml: {__html: '<strong>some text</strong>'}
}

defaultSelection对象从.js文件传递到组件

<HtmlSnippet innerHtml={defaultSelection.innerHtml} />

HTMLSnippet组件

var HtmlSnippet = React.createClass({
  render: function() {
    return (
      <span dangerouslySetInnerHTML={this.props.innerHtml}></span>
    );
  }
});

Plunkr示例

对文档进行危险的反应SetInnerHTML


1

您还可以在组件上使用一个函数来将jsx传递给props。喜欢:

 var MyComponent = React.createClass({

   render: function() {
    return (
      <OtherComponent
        body={this.body}
      />
    );
   },

   body() {
     return(
       <p>This is <strong>now</strong> working.<p>
     );
   }

});

var OtherComponent = React.createClass({

  propTypes: {
    body: React.PropTypes.func
  },

  render: function() {
     return (
        <section>
          {this.props.body()}
        </section>
     );
  },

});


1

来自html-react-parser的解析器是一个很好的解决方案。你只需要

  • 用npm或yarn安装
  • 从'html-react-parser'导入解析器;
  • 用:

    <MyComponent text=Parser("This is <strong>not</strong> working.") />

    而且效果很好。


1

添加到答案:如果您打算解析,并且已经在JSX中,但是有一个带有嵌套属性的对象,那么一种非常优雅的方法是使用括号来强制JSX解析:

const TestPage = () => (
  <Fragment>
    <MyComponent property={
    {
      html: (
        <p>This is a <a href='#'>test</a> text!</p>
      )
    }}>
    </MyComponent>
  </Fragment>
);

1

这个问题已经有很多答案,但是我做错了与此相关的事情,我认为值得分享:

我有这样的事情:

export default function Features() {
  return (
    <Section message={<p>This is <strong>working</strong>.</p>} />
  }
}

但是按摩的时间比那更长,所以我尝试使用如下方法:

const message = () => <p>This longer message is <strong>not</strong> working.</p>;

export default function Features() {
  return (
    <Section message={message} />
  }
}

我花了一段时间才意识到我在函数调用中缺少()。

不工作

<Section message={message} />

加工

<Section message={message()} />

也许对您有帮助,就像对我一样!


1

您可以成功地将React片段用于此任务。根据您使用的React版本,您可以使用短语法:<>或完整标签:<React.Fragment>。如果您不想将整个字符串包装在HTML标签中,则效果特别好。

<MyComponent text={<>Hello World. <u>Don't be so ruthless</u>.</>} />

-9

已使用jQuery追加在componentDidMount中追加了html。这应该可以解决问题。

 var MyComponent = React.createClass({
    render: function() {

        return (
           <div>

           </div>
        );
    },
    componentDidMount() {
        $(ReactDOM.findDOMNode(this)).append(this.props.text);
    }
});

5
这是不赞成的,因为您不应该将jquery的直接DOM操作与react的间接DOM操作结合使用,因为它可能导致浏览器崩溃。
艾莉森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.