简体   繁体   English

React:在危险的SetInnerHTML 中使用React 组件

[英]React: using React component inside of dangerouslySetInnerHTML

I have a question about using React.我有一个关于使用 React 的问题。 As you can see from the title, I'm wondering if it is possible to use React component (that is created by React.createClass ) inside of dangerouslySetInnerHTML property.从标题中可以看出,我想知道是否可以在dangerouslySetInnerHTML React.createClass属性中使用 React 组件(由React.createClass创建)。 I have tried, but React just prints code without transformation like this:我试过了,但 React 只是打印代码而不进行转换,如下所示:

const MySubComponent = React.createClass({
    render() {
        return (<p>MySubComponent</p>);
    }
});

...

let myStringHTML;
myStringHTML += "<ul>";
myStringHTML += "    <li>";
myStringHTML += "        <MySubComponent />";
myStringHTML += "    </li>";
myStringHTML += "</ul>";

const MyComponent = React.createClass({
    render() {
        return (
            <div dangerouslySetInnerHTML={{__html:myStringHTML}}></div>
        );
    }
});

I expected我期待

<ul>
    <li>
        <p>MySubComponent</p>
    </li>
</ul>

but the code is just same as original string, and that means React didn't transform MySubComponent .但代码与原始字符串相同,这意味着 React 没有转换MySubComponent

Is there a way to solve this problem?有没有办法解决这个问题? Above example is just simple but my actual code is quite complicated.上面的例子很简单,但我的实际代码非常复杂。 It will be very thanks gimme a hand ;)非常感谢帮我一把;)

Old question but for future wonderers I think I might have a solution to this but do note that this will definitely break your redux flow if you're using it in your project.老问题,但对于未来的好奇者,我想我可能有一个解决方案,但请注意,如果您在项目中使用它,这肯定会破坏您的redux流程。

Basically, you should have some id in your dangerousSetInnerHTML text.基本上,你应该在你的dangerousSetInnerHTML文本中有一些id
The idea is to mount to that id in the componentDidMount lifecycle hook after your "dangerous HTML" has been mounted to DOM.这个想法是在你的“危险的 HTML”被挂载到 DOM 之后挂载到componentDidMount生命周期钩子中的那个id

eg例如

const myStringHTML = `
  <div id="someid">
    some text in my dangerous html
  </div>
`;

const MySubComponent = React.createClass({
    render() {
        return (<p>MySubComponent</p>);
    }
});

...

let myStringHTML;
myStringHTML += "<ul>";
myStringHTML += "    <li>";
myStringHTML += "        <MySubComponent />";
myStringHTML += "    </li>";
myStringHTML += "</ul>";

const MyComponent = React.createClass({

    componentDidMount() {
      ReactDOM.render(<MyComponent />, document.querySelector('#someid'));
    }

    render() {
        return (
            <div dangerouslySetInnerHTML={{__html: myStringHTML}}></div>
        );
    }
});

Do note that componentDidMount will however not be called on component updates.做注意到componentDidMount但我们不能够在组件更新调用。 For more info on this refer to the lifecycle hook of react .有关更多信息,请参阅react生命周期钩子

Fair warning though that this does feel hacky and it is.公平的警告,尽管这确实让人感觉很棘手,但确实如此。 This also has its limitations as I mentioned some above but there can be time where you have no other option but to use dangerousSetInnerHTML and at times like this, this is an option.这也有我提到的一些之上,但可以有时间,你没有其他选择,只能使用其局限性dangerousSetInnerHTML ,并在这样的时代,这是一个选项。 At other times do what @Rohit Singh Sengar suggested and try to do it in react .在其他时候,按照@Rohit Singh Sengar 的建议去做,并尝试在react做到这一点。

dangerouslySetInnerHTML expects a JS object with __html property which should be valid HTML markup. dangerouslySetInnerHTML希望用JS对象__html这应该是有效的HTML标记属性。 Instead you are providing <MySubComponent /> there and expecting it to render that component's html.相反,您在那里提供<MySubComponent />并期望它呈现该组件的 html。 React won't process <MySubComponent /> there. React 不会在那里处理<MySubComponent /> dangerouslySetInnerHTML as name suggests should be avoided.顾名思义,应该避免dangerouslySetInnerHTML SetInnerHTML。 Moreover what you are trying to accomplish here can easily be done through React only.此外,您在这里尝试完成的工作可以仅通过 React 轻松完成。

const MySubComponent = React.createClass({
    render() {
        return (<li><p>MySubComponent {this.props.index}</p></li>);
    }
});

const MyComponent = React.createClass({
    render() {
        let subComponentList = [];
        [1,2,3,4,5].forEach(function(i){
            subComponentList.push(<MySubComponent key={i} index={i} />);
        }); 
        return (
            <ul>{subComponentList}</ul>
        );
    }
});

ReactDOM.render(<MyComponent />, mountNode);

Another approach would be to open a react portal.另一种方法是打开一个反应门户。 Ensure that the element has rendered and then simply确保元素已呈现,然后简单地

ReactDOM.createPortal(<YourComponent>,document.querySelector('selector'));

This is the cleanest way so far i have found to achieve this.这是迄今为止我发现实现这一目标的最干净的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM