How to detect a React component vs. a React element?
JavascriptReactjsJavascript 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
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
.