How to detect a React component vs. a React element?

JavascriptReactjs

Javascript Problem Overview


React.isValidElement tests true for both React components as well as React elements. How would I test, specifically, that an object is a React component? Currently, I'm doing it by testing typeof obj.type === 'function', but I'm hoping there's a better way.

Javascript Solutions


Solution 1 - Javascript

If you really want to type check for

  • component vs element

  • class vs functional component

  • DOM vs Composite Element

You could try something like this.

function isClassComponent(component) {
    return (
        typeof component === 'function' && 
        !!component.prototype.isReactComponent
    )
}

function isFunctionComponent(component) {
    return (
        typeof component === 'function' && 
        String(component).includes('return React.createElement')
    )
}

function isReactComponent(component) {
    return (
        isClassComponent(component) || 
        isFunctionComponent(component)
    )
}

function isElement(element) {
    return React.isValidElement(element);
}

function isDOMTypeElement(element) {
    return isElement(element) && typeof element.type === 'string';
}

function isCompositeTypeElement(element) {
    return isElement(element) && typeof element.type === 'function';
}

USE

// CLASS BASED COMPONENT
class Foo extends React.Component {
  render(){
      return <h1>Hello</h1>;
  }
}

const foo = <Foo />;

//FUNCTIONAL COMPONENT
function Bar (props) { return <h1>World</h1> }
const bar = <Bar />;

// REACT ELEMENT
const header = <h1>Title</h1>;

// CHECK
isReactComponent(Foo); // true
isClassComponent(Foo); // true
isFunctionComponent(Foo); // false
isElement(Foo); // false

isReactComponent(<Foo />) // false
isElement(<Foo />) // true
isDOMTypeElement(<Foo />) // false
isCompositeTypeElement(<Foo />) // true

isReactComponent(Bar); // true
isClassComponent(Bar); // false
isFunctionComponent(Bar); // true
isElement(Bar); // false

isReactComponent(<Bar />) // false
isElement(<Bar />) // true
isDOMTypeElement(<Bar />) // false
isCompositeTypeElement(<Bar />) // true

isReactComponent(header); // false
isElement(header); // true
isDOMTypeElement(header) // true
isCompositeTypeElement(header) // false

Example Codepen

Solution 2 - Javascript

The simplest solution is:

React.isValidElement(element)

Solution 3 - Javascript

In addition to @EmanualJade answer, you can use this to check if a variable is a function component

React.isValidElement(Component())

As @Leonardo has pointed out, some compilers can cause this to fail:

String(component).includes('return React.createElement')

Solution 4 - Javascript

ReactComponent.prototype.isReactComponent = {};

#33 of /node_modules/react/lib/ReactComponent.js Install using npm. At this point, there is no direct method available to check for its validity. What you are doing is correct.

Solution 5 - Javascript

This is an old question, with an old answer.

If you run into this issue, probably you'll want to check the react-is NPM package page: https://www.npmjs.com/package/react-is

It's an official React module that takes into account details like ref forwarding, and memo to check for an element type.

To check if a value is an element type do: ReactIs.isValidElementType(obj)

Solution 6 - Javascript

class Test extends React.Component {}

console.log(!!Test.prototype.isReactComponent);

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Solution 7 - Javascript

If you want to know what class you have for a particular instance of an object variable, then what you want is the instanceof operator...

function isHTMLElement(obj) {
    return (obj instanceof HTMLElement);
}

I tested with both document.createElement('div') (returns true) and <someReactJSComponent /> (returns false).

instanceof is a powerful and useful tool in JavaScript. Check out the official MDN documentation for it: Mozilla Documentation Network: instanceof

> "The instanceof operator tests the presence of constructor.prototype in object's prototype chain."

In addition, I have uploaded a code sample with a code-sandbox online to demonstrate the above principle...

Online Code Sandbox :

https://codesandbox.io/s/kmxjq27ol5

Code :

function App() { return (//insert JSX here//);};
const app = App();
const ele = document.createElement("div");
const rootElement = document.getElementById("root");
ReactDOM.render(app, rootElement);
console.log(
  "Hello!  Is a React Component HTML???" +
    (app instanceof HTMLElement) +
    "|  Is an HTML element HTML???" +
    (ele instanceof HTMLElement) +
    "|"
);

Code Results :

Hello!  Is a React Element HTML???false|  Is an HTML element HTML???true|

No problem (tested Chrome and FF). Just use instanceof.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjedmaoView Question on Stackoverflow
Solution 1 - JavascriptEmanual JadeView Answer on Stackoverflow
Solution 2 - JavascriptJackkobecView Answer on Stackoverflow
Solution 3 - JavascriptChristopher RegnerView Answer on Stackoverflow
Solution 4 - JavascriptAnvesh CheckaView Answer on Stackoverflow
Solution 5 - JavascriptDiegoView Answer on Stackoverflow
Solution 6 - JavascriptRazzwanView Answer on Stackoverflow
Solution 7 - JavascriptHoldOffHungerView Answer on Stackoverflow