【问题标题】:React: using React component inside of dangerouslySetInnerHTMLReact:在 dangerouslySetInnerHTML 中使用 React 组件
【发布时间】:2016-08-27 00:02:00
【问题描述】:

我有一个关于使用 React 的问题。正如您从标题中看到的那样,我想知道是否可以在 dangerouslySetInnerHTML 属性中使用 React 组件(由 React.createClass 创建)。我试过了,但是 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

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

【问题讨论】:

    标签: reactjs


    【解决方案1】:

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

    基本上,您的dangerousSetInnerHTML 文本中应该有一些id
    这个想法是在将“危险的 HTML”挂载到 DOM 之后,在 componentDidMount 生命周期挂钩中挂载到 id

    例如

    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 在组件更新时不会被调用。有关这方面的更多信息,请参阅lifecycle hook of react

    公平的警告,虽然这确实感觉 hacky 确实如此。正如我在上面提到的那样,这也有其局限性,但是有时您没有除了使用dangerousSetInnerHTML之外别无选择,在这种情况下,这是一个选项。其他时候按照@Rohit Singh Sengar 的建议去做,并尝试在react 中做。

    【讨论】:

    • 请注意 - 您不能在功能性 React 组件中使用 componentDidMount,如此处所示,您可以使用 useEffect 挂钩。这并不完全相同,因为 useEffect 在组件绘制到屏幕上之后运行,而 componentDidMount 在之前运行,但它是功能组件中最接近它的东西。
    【解决方案2】:

    dangerouslySetInnerHTML 需要一个带有 __html 属性的 JS 对象,该属性应该是有效的 HTML 标记。相反,您在那里提供 &lt;MySubComponent /&gt; 并期望它呈现该组件的 html。 React 不会在那里处理&lt;MySubComponent /&gt;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);
    

    【讨论】:

    • 谢谢。我还认为由于名称而使用“dangerouslySetInnerHTML”不好;)
    【解决方案3】:

    另一种方法是打开一个反应门户。确保元素已经渲染然后简单

    ReactDOM.createPortal(&lt;YourComponent&gt;,document.querySelector('selector'));

    这是迄今为止我发现的最干净的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多