Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Allow multiple instance of React (or inject one into the other) #22159

Closed
grantila opened this issue Aug 23, 2021 · 4 comments
Closed

Bug: Allow multiple instance of React (or inject one into the other) #22159

grantila opened this issue Aug 23, 2021 · 4 comments
Labels
Resolution: Stale Automatically closed due to inactivity Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@grantila
Copy link

FYI; Not sure if this is a bug or a feature request. It's a problem that is surprising when it happens, and there's no workaround I'm aware of.

Now that since 17, React is supposed to more easily be upgradable in that using components from an older/newer React in a different version will still work (and be supported), the ability to run multiple instances concurrently should be approached again.

From what I can see, this can be achieved in multiple ways;

  • Seamlessly allowing multiple concurrent React instances at once, or
  • Seamlessly re-using the same global scope React when importing/requiring consecutively, or
  • Allowing manual injection of one React instance into another

There are use cases for this, e.g. when using a component from a webpage in a jsdom environment. This is working for passive components not using any hooks, but as soon as you need hooks (or lifecycle management in general I suppose), the Invalid Hook Call Warning (referenced in #13991) is triggered, due to "3. You might have more than one copy of React in the same app."

Consider the following code, which simulates a web page using React, which exposes a component on the global object "window" (this could be done in multiple ways, the implementation detail here is irrelevant). When running this webpage in a jsdom environment, using the web page's component from an outer context (potentially not even using react-dom but a custom reconciler), the "Invalid Hook Call Warning" is triggered. The example also shows where an outer React instance could be injected into another React (another global scope) if this was supported somehow:

import React, { PropsWithChildren } from 'react';
import { renderToString } from 'react-dom/server';
import { JSDOM } from "jsdom";


async function getRemoteComponent(): Promise<React.ElementType> {
  const html = `
  <html lang="en">
    <body>
      <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
      <script>
        const component = () => {
          const [content] = React.useState('from webpage');
          return React.createElement( 'span', {}, [content] );
        }
        window.setComponent(component);
      </script>
    </body>
  </html>`;

  return new Promise((resolve, reject) => {
    new JSDOM(html, {
      url: 'http://localhost',
      runScripts: "dangerously",
      resources: "usable",
      beforeParse(window) {
        // If React would support something like this, it would solve the problem:
        // window.React = React;

        (window as any).setComponent = component => {
          resolve(component);
        };
      },
    });
  });
}

function Outer({children}: PropsWithChildren<{}>) {
  return <div>{children}</div>
}

getRemoteComponent()
.then( Inner => renderToString( <Outer><Inner /></Outer> ) )
.then( domString => console.log( `Result: ${domString}` ) );

Expected output (which you get when not using any hook):

Result: <div data-reactroot=""><span>from webpage</span></div>

There are two closed issues related to this, but with a different approach and not about actually enabling this afaict: #2402 and #3252
There's also #13991, but is mostly for how to detect when you have multiple instances concurrently, often due to packaging/bundling/dependency issues. This is not the same as intentionally using multiple instances.

@grantila grantila added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Aug 23, 2021
@grantila
Copy link
Author

For some extra context, it is possible to hack around this, but there's no official "supported" way, which is what I'm after.

In the example above, when fetching React from a <script> tag, it'll add itself to window.React, so that is overwriteable (as long as you overwrite it after it's been adding itself to window obviously). But is this supported?

When building a web app with webpack and using es modules, React won't register itself to window, however I found that:

import React from 'react';
Object.assign(React, NewReactFromSomewhere);

works. But this is especially horrible, and although it "seems to work", it's surely not officially supported I presume?

@lubieowoce
Copy link
Contributor

Another possible workaround: You could use webpack externals (or equivalent from another bundler) to make sure the same React instance is used everywhere without hacking around "in userspace". (ReactDOM needs the same treatment iirc)

And I hope I don't sound like a Webpack shill 😄 But if you're using Webpack and doing stuff with "remote components", Module federation may be interesting to you. They even have an example that says it makes multiple React versions work together somehow.

Copy link

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Apr 10, 2024
Copy link

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Stale Automatically closed due to inactivity Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests

2 participants