14

As a library author, I'd like to know whether my library is being used with React or with some other UI framework (Vue, Svelte, ...).

Is there a way to detect whether React's code was loaded?

The following Stack Overflow answers don't answer this question because they only work using the developer console. (Whereas I want to detect React from the perspective of a JavaScript library.)

Context: I'm building vite-plugin-ssr. (It's like Next.js/Nuxt but as a do-one-thing-do-it-well Vite plugin.)

EDIT: I need to be able to detect React as soon as React is loaded in the browser, before React even renders/hydrates the page. So far, all answers below are detecting React too late.

19
  • the 2nd link you post shows how to do it from vanilla javascript Commented Jul 28, 2022 at 16:54
  • 1
    Not 100% reliable since people can try to turn off dev tools, but this might be useful: How does React Developer Tools determine that the webpage is using React? Commented Aug 22, 2022 at 15:49
  • 1
    @David Fong The accepted answer doesn't work reliably, see its comments. And it actually never works in my specific use case. Commented Aug 22, 2022 at 18:49
  • 1
    Imagine a user clicking on a link before the hydration is finished: vite-plugin-ssr can then abort the hydration and render the new page. Commented Nov 13, 2022 at 15:12
  • 1
    @aifrim Yep, that's what I'm currently doing. Commented Nov 16, 2022 at 15:58

4 Answers 4

11
+50

I've come up with the following solution:

const isReactApp = !!Array.from(document.body.querySelectorAll("*")).find((node) => node._reactRootContainer)

It works on create-react-app as well as gatsby projects (possible more as I've tested only those so far).

Basically it traverses through all elements and check if the magic reactRootContainer attribute is defined on the element. Consider that the snippet could be very slow on huge pages with lots of DOM nodes.

However, I would generally advise against using this approach as it's likely that the reactRootContainer property will change (since it's private) in the near future.

A better approach would be to let the developers who'll use your library tell your library that they are using react (or vue or svelte or x).

Something like:

import MyLibrary from '@mylibrary/react';

EDIT: Another approach I've found which could work for most react projects as long as they attach any event handler:

// find the reactEvents${....} variable in the document.
!!Object.keys(document).find(key => key.includes('react'))
Sign up to request clarification or add additional context in comments.

5 Comments

Interesting trick. Although, if there are a lot of DOM elements, that could impact performance?
Yeah that would definitely impact performance quite bit. Although once it actually finds the react node it will stop to search it still traverses through the DOM. I've updated my answer with another hacky-way to detect react which does not traverse the DOM.
This is very similar to the answer I first came up with here where I give an optimization to filter by nodes with the id attribute with the caveat that it works only under the assumption that a site will usually give the react root an id to make it easy to initialize.
The approach added in the edit doesn't seem solid. Anything that added something to do the document containing the string "react" would falsely be picked up.
You could also check for reactEvents$ instead of react but it's still a hacky solution.
0

This worked for me. Instead of detecting react on the runtime, you can detect it on the build time.

let react: any;
try {
  react = require("react");
  console.log("react detected");
} catch (err) {
  console.log("no react detected");
}

Then your hook on the runtime just throws an error when there is no react.

export function useMyHook() {
  if (!react) throw new Error("react is undefined");
  const [state, setter] = react.useState();
}

Comments

-1

You can detect if an application is using React using this way:

const isUsingReact = window.__REACT_DEVTOOLS_GLOBAL_HOOK__ 
  && window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.size > 0

This is the way used by the official extension, so I think it's reliable.

https://github.com/facebook/react/blob/d483463bc86555decb3e8caa18459d1d0f7c0148/packages/react-devtools-extensions/src/main.js#L57

1 Comment

Unfortunately, React seems to populate __REACT_DEVTOOLS_GLOBAL_HOOK__.renderers fairly late and size is 0 at page load.
-1

The closest i could come up to automatically getting the info (based on How to tell if a web application is using ReactJs) without continuously scanning the whole DOM is to use a MutationObserver to detect changes in the DOM and check for _reactRootContainer on the mutated element.

function onReactLoad(callback) {
  const observer = new MutationObserver((mutationList) => {
    const hasReact =
      const hasReact = mutationList.some(({
        target
      }) => target._reactRootContainer !== undefined);
      
    if (hasReact) {
      callback();
      observer.disconnect();
    }
  });

  observer.observe(document.body, {
    subtree: true,
    childList: true
  });
}

// usage
onReactLoad(() => {
  console.log('react detected')
});

Comments

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.