Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use React in multiple places in a normal website

I have a new website which isn't a single page app but a server rendered website (asp.net using Umbraco CMS). I used to use Angular 1.x in my websites, which is easy because you just load it in with script tags and the code is uncompiled.

I have been using React recently in SPAs started with create-react-app which looks after webpack, babel etc. for you and produces a single bundle. However, I want to use React in several places on the website like the main header/menu, contact forms etc so it makes sense to produce multiple bundles, although these bundles may share imports (Moment.js, Formik etc.).

There are instructions on the React website showing how to include a single script and attach it to an element in yourwebsite, but no complex examples.

So, how do I go about setting up something that will transpile everything without duplicating code in bundles. Do I need some kind of master bundle loaded on all pages and individual bundles for things like a contact form?

Secondly, how do I wire everything up? In an SPA you just have a root node and bind your app to the root node using react-dom, but if you've got mini pieces of react functionality littered through your app then do you need some kind of master script to bind everything to the right elements?

Any help would be greatly appreciated, even if it's just pointing me in the direction of some kind of boilerplate project.

Oh, and I'm not interested in doing a server side rendered Next JS app or anything like that, I think that could get too complicated to integrate with the CMS.

like image 840
jonhobbs Avatar asked Dec 13 '18 15:12

jonhobbs


3 Answers

I think you can make a single bundle, rendering multiple component to different places. I created a little example:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  return (
    <div className="App">
      <h1>Body</h1>
    </div>
  );
}

function Footer() {
  return (
    <div className="App">
      <h1>Footer</h1>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

const footerElement = document.getElementById("footer");
ReactDOM.render(<Footer />, footerElement);

You can play with it in this sandbox example. https://codesandbox.io/s/34nvv4nvy5

like image 194
Peter Ambruzs Avatar answered Oct 19 '22 07:10

Peter Ambruzs


In addition to the answer above you can exclude React, ReactDOM or/and React Router (and any other dependencies) from your bundles and include them on the page so you aren't bundling them X amount of times. This way you can have separate entry files for each application.

webpack.config.js

externals: {
    'react': 'React',
    'react-dom': 'ReactDOM',
}

index.html

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js" integrity="sha256-JBRLQT7aJ4mVO0H2HRhGghv/K76c5WzE57wW0Flc6ZY=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/cjs/react-dom.production.min.js" integrity="sha256-j2ERTIovDFVe0R+s0etuSiBQ2uxrNE6q0ow/rXxHvLA=" crossorigin="anonymous"></script>
like image 35
Win Avatar answered Oct 19 '22 06:10

Win


If you want to render elements "outside" your root element of the react application, then you can use react Portals. We are using this approach as well and it's going well.

If you still think you want multiple mini react applications that run on the same page, you can communicate with them with the help of ReactDOM.render. Basically, ReactDOM.render can get invoked multiple times, it won't re-mount the entire application but instead will trigger updates and diffing to the react tree (same as a normal render method of components).

In fact, i wrote an article with a tutorial on how to Integrate React with other applications and frameworks.

I also tried to simulate this approach with a codesandbox example

Hope that helps.

like image 1
Sagiv b.g Avatar answered Oct 19 '22 07:10

Sagiv b.g