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.
-
obj.type can be a symbol or a string as well.Miguel Carvajal– Miguel Carvajal2019-06-10 07:56:50 +00:00Commented Jun 10, 2019 at 7:56
8 Answers
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
8 Comments
function FnChild(props) { return _react2.default.createElement('div', { id: 'child-fn' }); }String(component).includes('return React.createElement') will not work in many cases.React.forwardsRef.The simplest solution is:
React.isValidElement(element)
3 Comments
typeof element === 'function' first, too. I was trying to render either a string or a React componentfalse on a working, functional React component, using this method :/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')
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)
Comments
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.
3 Comments
instanceof(), it worked perfectly, and it's only 10 characters, whereas ReactComponent.js is an entire package. Why not just use something built-in that's much shorter?Checks if something is a React component or an Array of components:
// checks if the argument is a React component or an Array of components
const isReactComp = v => React.isValidElement(v) ||
(
Array.isArray(v) &&
v.every(node => React.isValidElement(node))
);
const Test = ({children}) => <div>{isReactComp(children) + ''}</div>;
const MemoedComp = React.memo(({children}) => children);
// Render
ReactDOM.render(
<div>
<Test>hello</Test>
<Test><i>hello</i></Test>
<Test>{[<i key={1}>hello</i>]}</Test>
<Test><MemoedComp>hello</MemoedComp></Test>
</div>
, root)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Comments
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.
5 Comments
instanceOf is well-documented in MDN developer documentation. If there's any use in this answer, it's that all the other answers on this page will fail when used in the simple, 2-line sandbox demo I posted. Cheers!var testcomp = <TestComponent />; console.log("TEST " + isClassComponent(testcomp) + "|"); // Results: "TEST false". Notice the other functions, to determine if a react-element, use the isClassComponent(), yet it returns false for a legitimate React class component. Hope this helps!