4

I have an old web application running with HTML/JS. I have created a new react application and my goal is to start developing new features / pages using React, and implement them in the current application.

The main goal is to use React components outside react, for example:

<html>
<head>
<title> My old web applciation</title>
// Imports for my react app / components
</head>
<body>

<!-- Old staff -->

<Footer someProp="1"/>

</body>
</html>

What I have so far:

  • For full-page features I used Iframe (and created a route in React for it)

  • Using element ID, e.g::

and in react:

const GiveItem = ({ ...props }) => {

  console.log("init give item component");

  return (
    <section>
     Give Item
    </section>
  );
};

try {
  const domContainer = document.querySelector('#giveItem');
  render(e(GiveItem), domContainer);
} catch (e) {
  console.error('Failed to render give item', e);
}

export default GiveItem;

Is there any legitimate way to "export" react components to HTML (outside react) and use them as native components like:

<GiveItem someProp="1"/>

Using Vue I managed to do it, just by wrapping the highest-level element with:

    <div id="vapp">

 .... My old code

<VueComponent />

So back to the question - How I can show/use React components in different parts of legacy app as native HTML components?

Thanks!

TheUnreal
  • 23,434
  • 46
  • 157
  • 277

1 Answers1

7

I will divide my answer into 3 parts:

  1. simple inclusion of react in general
  2. make your example work
  3. modules

(I will use yarn below. You can use npm as well, I assume you are familiar with these.)

1. simple inclusion of react in general

See Add React to a Website.

index.html:

<html><head>
    <title>My old web applciation</title>
</head><body>

<h1>old stuff</h1>
<p>Some old HTML content.</p>

<!-- add a container, where you want to include react components -->
<div id="injected-react-content"></div>

<!-- import the react libraray -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>

<!-- import your react component -->
<script src="GiveItem.js"></script>

</body></html>

GiveItem.js:
(modified from JSX to JS. For JSX see section 2.)

const GiveItem = (props) => {
    console.log("init give item component");
    return React.createElement(
        "section",
        null,
        "Give item content"
    );
};

const domContainer = document.querySelector('#injected-react-content');

ReactDOM.render( React.createElement(GiveItem), domContainer );

2. make your example work

Your component uses JSX. You need to transpile it to JS, using babel.

GiveItem.jsx:
(it is not necessary to call it .jsx, but it makes sense)

const GiveItem = (props) => {
    return (
        <section>
            Give Item
        </section>
    );
};

const domContainer = document.querySelector('#injected-react-content');
ReactDOM.render( React.createElement(GiveItem), domContainer );

Install babel:

yarn add @babel/cli @babel/core @babel/plugin-transform-react-jsx @babel/preset-react --dev

Transpile your JSX file ./src/GiveItem.jsx into a JS file in ./dist/GiveItem.js:

yarn babel ./src/GiveItem.jsx --presets=@babel/preset-react --out-dir dist

(the dist folder will be created if it doesn't exist)

If you now copy the index.html into ./dist, you should have the same code as in section 1., and opening ./dist/index.html in the browser should work.

3. modules

Of course, you would want to import other react components and sub-components.
(And you probably don't want to import everything individually with <script> tags.)

if an environment is set up already

Maybe your old app already runs in a yarn (or npm) environment, then you might be fine with

  • install yarn add react and yarn add react-dom
  • removing the two <script src="https://unpkg.com/react... lines (as react is probably already imported inside your components),
  • then import some root component (instead of GiveItem.js before), where you do the ReactDOM.render(...) and import further modules:

E.g.:

index.html:

<!-- import your react component -->
<script type="module" src="EntryIntoReactWorld.js"></script>

EntryIntoReactWorld.js:

import SomeComponent from './SomeComponent';
import SomeOtherComponent from './SomeOtherComponent';

const ReactRoot = props => {
  return React.createElement(
      "div",
      null,
      React.createElement(SomeComponent, null),
      React.createElement(SomeOtherComponent, null)
  );
};

ReactDOM.render(
    React.createElement(ReactRoot),
    document.querySelector('#injected-react-content')
);

if environment is not set up already

If your old app is not already running in a yarn (or npm) environment, you have to set one up.

Unfortunately, this is not trivial.
(I tried to write a short working minimal example here, but I failed.)

For that you have to enter the world of Javascript modules. But modern browsers don't allow many things from the local file system. (e.g. see CORS problems, MIME problem, ...)

You have to install a server for development. You might start with e.g. http-server, but there you probably still will have problems, so I suggest to already start with writing a server.js file and use node http. (Maybe expressjs as well. It is not necessary, but everybody uses it, and it is easier to find help and tutorials.)

You also might need webpack.

Of course you also have to install yarn add react and yarn add react-dom.

kca
  • 4,856
  • 1
  • 20
  • 41
  • Wowww! What an answer! Thanks. My legacy project is simple HTML/JS Based legacy app, no npm or yarn. I kinda lost you from the "modules" part – TheUnreal Jan 29 '21 at 16:52
  • For inline babel see also https://stackoverflow.com/questions/69607103/react-component-not-displayed-in-html/69620365#69620365: `` ... ` – kca Nov 20 '21 at 10:56