'Check if a component is an instance of React.ReactElement<any> in a child map
I have a component that loops through children and wraps them in a div. I am trying to add an exclusion to that, but running into an issue where I can't check if the child is a ReactElement
or not (React.ReactChild
can be a string, or a number so it may not have a type).
Trying the method below I receive: "'ReactElement' only refers to a type, but is being used as a value here." as well as "Property 'type' does not exist on type 'ReactChild'."
Any help pointing me in the right direction would be greatly appreciated.
{React.Children.map(children, (child: React.ReactChild) => {
/**
* Exclude these components from being
* wrapped by the item wrapper.
*/
if (child instanceof React.ReactElement<any> && child.type === Divider) {
return child;
}
if (child) {
return <div className="l-spacer__item">{React.cloneElement(child as React.ReactElement<any>)}</div>;
}
return null;
})}
Solution 1:[1]
child instanceof React.ReactElement<any>
is invalid because React.ReactElement
is not a value. It is an interface. Interfaces are just types, and unlike classes, have no corresponding value. All types are erased. They have no runtime representation.
Furthermore, JavaScript's instanceof
is used, and should be understood, as follows
value instanceof anotherValue
This confuses people coming from syntactically similar languages with similarly named operators but wherein the right hand operand is a type. In JavaScript both operands are always values.
To perform your specific check, adjust your code to something along the lines of
if (typeof child !== 'string' && typeof child !== 'number' && child.type === Divider) {
return child;
}
This works because the type React.ReactChild
is defined as
React.ReactElement | React.ReactText;
and React.ReactText
is defined as
string | number
By elminating those cases, the language knows it matches the third possible union case, React.ReactElement
, which has a type
property.
Solution 2:[2]
You should use React.isValidElement. For your case above:
if (React.isValidElement(child) && child.type === Divider) {
return child;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | mofojed |