2

So I have two apps, one is a legacy app which was built using react 15.3 and another app which is being built using react 16.7. The newer app is built to accommodate a feature request which was not originally available to the legacy app. Both apps run smoothly on their own but when merged is just pure chaos. The goal is for both apps is to communicate even at a minimal level (e.g. passing parameters, props, variables, etc).

Things that I tried:

  1. I built the newer app and then added another div in the HTML file so that both apps would run on the same page but they would not have interaction. (Works but doesn't meet the goal)
  2. I built a minified js file of the newer app then imported it in the older app as a component. (Does not work)
  3. I salvaged components from the newer app then copied them over to the older app. (Does not work)

My futile attempts would lead me to the conclusion that either of the two apps needs to be upgraded/downgraded. I am leaning towards the upgrade of the legacy app because of the dependencies of the newer app and other stuff(e.g. es6). It would be great if someone could point me in the right direction.

1 Answer 1

2

This can be achieved by rendering React 15 and React 16 applications separately.

React 15 components should be created with React.createElement and rendered with ReactDOM.render that belongs to React 15, the same applies to React 16 application. This can be achieved if React 15 application is bundled separately and imported into React 16 application, this guarantees that their react and react-dom dependencies are kept apart.

Here's an example. In order to avoid conflicts between react@15 and react@16 packages React 15 is used as a global:

  <head>
    <script src="https://unpkg.com/[email protected]/dist/react.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/react-dom.js"></script>
    <script>
      window.React15 = window.React;
      window.ReactDOM15 = window.ReactDOM;
      delete window.React;
      delete window.ReactDOM;
    </script>
  </head>

And React 16 is used as NPM dependency.

React 15 application:

export const React = window.React15;
export const ReactDOM = window.ReactDOM15;

export class React15Component extends React.Component {
  static getDerivedStateFromProps() {
    throw "Should not support React 16 hook";
  }

  render() {
    return <div>Hello from {this.props.name}</div>;
  }
}

It's hosted by React 16 application:

import { React15Component, React as React15, ReactDOM as ReactDOM15 } from "./react15";

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

class React16Component extends React.Component {
  containerRef = React.createRef();

  static getDerivedStateFromProps({ name }) {
    name += "!";
    return { name };
  }

  componentDidMount() {
    ReactDOM15.render(
      React15.createElement(React15Component, { name: "React 15" }),
      this.containerRef.current
    );
  }

  render() {
    return (
      <>
        <div>Hello from {this.state.name}</div>
        <div ref={this.containerRef} />
      </>
    );
  }
}

ReactDOM.render(<React16Component name="React 16" />, document.getElementById("root"));
Sign up to request clarification or add additional context in comments.

6 Comments

I'm trying to wrap my head around this concept as both apps have different dependencies. Would I also have to make the React 15 app's dependencies global and keep React 16 app's dependencies in npm? When I tried to salvage components from my newer app to the older one its had errors when building because the older app didn't support arrow functions.
It depends on your setup. I've done it this way because this was the easiest thing to do in Codesandbox with single CRA project. You likely want to keep them in different projects and import a bundle from one project (React 15) into another project (React 16), as the answer suggests.
I see. That makes sense. So basically from what I understand; I have to import the bundled old React 15 app as a React 16 component to be able to run the whole thing as React 16, technically. Before I bundle the old app, I will have to remove the target div which the old React 15 app was supposed to be rendered. to. After that, the import can be done. Am I correct?
More or less. You also need to export ReactDOM15 from React 15 app to render it inside React 16 app as shown in the answer. This way you can communicate between thems via props.
Thank you. You're a lifesaver.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.