145

I want to use React to add components multiple times throughout the DOM. This fiddle shows what I'm looking to do, and it doesn't throw any errors. Here's the code:

HTML:

<div id="container">
    <!-- This element's contents will be replaced with the first component. -->
</div>

<div id="second-container">
    <!-- This element's contents will be replaced with the second component. -->
</div>

JS:

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

React.render(<Hello name="World" />, document.getElementById('container'));

React.render(<Hello name="Second World" />, document.getElementById('second-container'));

I've seen this question and I'm afraid that by doing the above, I'll be risking having React components interfere with each other. The answer to that question suggests using server-side rendering which isn't an option for me as I'm using Django server-side.

On the other hand, maybe what I'm doing is OK because I only have one instance of the React library mounted (as opposed to multiple components calling their own instance of React)?

Is this way of using multiple DOM instances an OK way to use React?

Community
  • 1
  • 1
YPCrumble
  • 26,610
  • 23
  • 107
  • 172

3 Answers3

161

Yes, it is perfectly fine to call React.render multiple times on the same page. Just as you've suggested, the React library itself is only loaded once, but each call to React.render will create a new component instance independent of any others. (In fact, such a situation is not uncommon on sites that are in the process of transitioning to React, where some portions of the page are generated using React.render and others are not.)

hopper
  • 13,060
  • 7
  • 49
  • 53
  • 12
    awesome - it's also extremely helpful in "supercharging" an existing Django app. I want to use Django for the rendered content to get the SEO, and use React for user interaction with DOM elements. This makes it super simple to achieve. – YPCrumble Jul 08 '15 at 20:42
  • 1
    you can probably also look at shouldComponentUpdate and it could boot up performance in the future (probably not in your case). Here's the reference: https://facebook.github.io/react/docs/component-specs.html – Jim Jul 09 '15 at 01:58
  • @YPCrumble if hoppers answer is correct, please mark it – Dana Woodman Jul 09 '15 at 02:55
  • And what about the case when there are multiple `ReactDOM.render()` that has to insert components in the same `div` depending on what page you open? In particularly, you have only one uglified concatenated `app.js` asset that you ` – Green Dec 09 '15 at 17:27
  • 3
    @Green I'm not sure I understand, if the components are on separate pages how would they interfere? Otherwise, why not add a new container element for each component, ie: `ReactDOM.render(, document.getElementById('content').appendChild(document.createElement('div')))` – hopper Dec 09 '15 at 17:45
  • Another approach, @Green, is to wrap your `ReactDOM.render()` calls in a conditional: `const mount1 = document.getElementById('#mount-1'); if(mount1) {ReactDOM.render(, mount1);}` so that you can have all your components in a single JS file, and the server can dictate which will render by outputting `div#mount-1` or not depending on the route. (This approach can be refined!) – ptim Nov 11 '16 at 10:27
  • I have the same react app for different purposes (i.e. comment) and they seem to be sharing a store... I want them to be independent from one an other. Any ideas? – Philll_t Jul 20 '17 at 00:08
  • @Philll_t actually you can create multiple separate stores and use it with multiple providers. But i would consider to look at your reducers first, seems there's just misuse of them, because it is okay to share a single store. It has to be an edge-case if you want multiple stores (REALLY edge, for example, when your store has so many elements it causes performance problems). If your case is about separating concerns you're fine with one store and different reducers. – UnstableFractal Sep 11 '18 at 07:05
  • How do this differ from react `portal`? – Codler Dec 09 '19 at 08:14
10

This approach is ok from a page load performance point of view, but there are other downsides and multiple React roots should be avoided if possible.

  • Different React roots cannot share context, and if you need to communicate between the React roots, you will need to fall back on global DOM events
  • You get less benefit from performance optimizations like time slicing - suspense and async rendering. It's not possible to suspend across React root boundaries

Further reading

Aryan Beezadhur
  • 4,503
  • 4
  • 21
  • 42
Yangshun Tay
  • 49,270
  • 33
  • 114
  • 141
  • Can I create a single `render` and inject react components with something like `insertAdjacentElement` but with React instead of actual DOM elements? – Diego Fortes Dec 09 '20 at 05:28
  • 1
    @DiegoFortes Yes, you can using `ReactDOM.createPortal`. https://reactjs.org/docs/portals.html – inwerpsel May 05 '21 at 13:37
7

If you were wondering if it's ok to use ReactDOM.render() multiple times with the same container, the docs say:

If the React element was previously rendered into [the same] container, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React element

Liam
  • 27,717
  • 28
  • 128
  • 190
David
  • 4,191
  • 2
  • 31
  • 40