React.render替换容器而不是插入

时间:2015-06-06 19:35:48

标签: reactjs

我正在逐步用React替换一些Backbone视图。

我的反应意见:

<div id="reactViewContent">Rendered By React</div>

我需要在其他html元素下面渲染React视图而不替换它们。

<div id="somestuff">
  <div id="anotherView">Other stuff not to delete</div>
  <div id="placeholderForReactView"></div>
</div>

我希望我的方法可以替换占位符而不是插入它,以便:

React.render(React.createElement(MyTestReactView), document.getElementById('placeholderForReactView'));

可能导致:

<div id="somestuff">
  <div>Other stuff not to delete</div>
  <div id="reactViewContent">Rendered By React</div>
</div>

而不是:

<div id="somestuff">
  <div>Other stuff not to delete</div>
  <div id="placeholderForReactView">
    <div id="reactViewContent">Rendered By React</div>
  </div>
</div>

如果没有在Jquery重复出现,有没有正确的方法呢?

6 个答案:

答案 0 :(得分:16)

您不需要jQuery来解决此问题。

您只需要渲染到临时DIV中并提取内容并替换现有元素。我添加了id="destination",以便可以从临时元素中轻松检索元素。

var Hello = React.createClass({
    render: function() {
        return <div id="destination">Hello {this.props.name}</div>;
    }
});

// temporary render target
var temp = document.createElement("div");
// render
React.render(<Hello name="World" />, temp);
// grab the container
var container = document.getElementById("container");
// and replace the child
container.replaceChild(temp.querySelector("#destination"), document.getElementById("destination"));

答案 1 :(得分:11)

不幸的是,目前React无法做到这一点。它取代了您渲染的任何元素的内容。

您现在可以做的最好的事情是分别渲染React组件,然后手动改变DOM以使其达到您想要的位置。

我希望你所寻求的功能不久就可以在React中使用,但还没有!

答案 2 :(得分:1)

应该这样做:

 * Replaces html node with react component
 * @param element
 * @param reactComponent
 */
export function replaceNodeWithReactComponent (element: HTMLElement, reactComponent: any) {
  const parent = document.createElement('div');
  ReactDOM.render(reactComponent, parent, () => {
    element.replaceWith(...Array.from(parent.childNodes));
  });
}

用法:

replaceNodeWithReactComponent(myHTMLelement, <MyReactComponent />);

答案 3 :(得分:0)

这似乎起作用:

const linkEl = <link href="https://fonts.googleapis.com/css?family=Cinzel&display=swap" rel="stylesheet"/>;
const linkElAsDirectChildOfHead = ReactDOM.createPortal(linkEl, document.head); // portal will do actual adding-to-head
ReactDOM.render(linkElAsDirectChildOfHead, document.createElement("div")); // render stub into never-added container

结果:

请注意,根据需要,它不会删除document.head中的其他子项。

不确定此方法是否有负面影响,但乍看之下它似乎可行。

答案 4 :(得分:0)

扩展@WiredPrairie 的解决方案,使用占位符元素的问题是,React 似乎从父元素获取事件,因此如果父元素不在 DOM 中的正确位置,则事件不会触发(这是我的无论如何都是理论)。

要解决此问题,您可以使用实际的父元素,但通过保留父子元素的副本来保留原始 DOM,然后稍后重新添加它们,大致如下:

https://jsfiddle.net/n41dzLx2/

const el = document.querySelector("#app");
const parent = el.parentNode;
const oldChildren = Array.from(parent.childNodes);

ReactDOM.render(
  <App />, 
  parent, 
  () => {
    const newChildren = Array.from(parent.childNodes);
    parent.replaceChildren(...oldChildren);
    el.replaceWith(...Array.from(newChildren));
  }
)

这在大多数情况下有效,但如果组件中的根元素发生变化,React 元素将移到父元素的末尾。

答案 5 :(得分:-1)

除非我遗漏了某些东西,否则你可以只渲染到父节点(假设它只有一个子容器):

[items]="ArrayLangauge"