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

IT技术 reactjs
2021-04-29 09:52:50

我有一个关于使用 React 的问题。正如您从标题中看到的,我想知道是否可以React.createClassdangerouslySetInnerHTMLproperty内部使用 React 组件(由我试过了,但 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>
        );
    }
});

我期望

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

但代码与原始字符串相同,这意味着 React 没有转换MySubComponent

有没有办法解决这个问题?上面的例子很简单,但我的实际代码非常复杂。非常感谢帮我一把;)

3个回答

老问题,但对于未来的好奇者,我想我可能有一个解决方案,但请注意,redux如果您在项目中使用它,这肯定会破坏您的流程。

基本上,你iddangerousSetInnerHTML文本中应该有一些
我们的想法是要安装到该idcomponentDidMount已经被安装到你的DOM“危险的HTML”后的生命周期挂钩。

例如

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

请注意,componentDidMount不会在组件更新时调用。有关更多信息,请参阅react生命周期钩子

公平的警告虽然这确实让人感觉很糟糕,但确实如此。这也有我提到的一些之上,但可以有时间在这里你它的局限性没有别的选择,只能使用dangerousSetInnerHTML在这样的时代,这是一个选项。其他时候按照@Rohit Singh Sengar 的建议去做,并尝试在react.

dangerouslySetInnerHTML需要一个具有__html属性的 JS 对象,该属性应该是有效的 HTML 标记。相反,您在<MySubComponent />那里提供并期望它呈现该组件的 html。React 不会<MySubComponent />在那里处理dangerouslySetInnerHTML顾名思义,应该避免。此外,您在这里尝试完成的工作可以仅通过 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);

另一种方法是打开一个react门户。确保元素已呈现,然后简单地

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

这是迄今为止我发现的最干净的方法来实现这一目标。