如何编写isReactComponent函数区分React组件与合法Styled Component?
How to Implement
isReactComponent to Block Forbidden Components While Allowing Valid Styled Elements Alright, let's break down how to solve this problem. You need a function that can reliably distinguish between forbidden React components (and styled-components wrapped around them) and allowed elements—either native HTML tags or styled-components built from those native tags. Here's a practical approach:
First, Understand the Structure of React Elements & Styled-Components
When you pass a JSX element to SophisticatedComponent, what you're actually passing is a React element object. The key to differentiation lies in the type property of this object:
- Native HTML elements (like
<div/>) have atypethat's a string (e.g.,"div"). - Custom React components (function or class) have a
typethat's a function/class. - Styled-components add a layer here:
- Styled components built from native tags (e.g.,
styled.div) have atypewith atargetproperty set to the native tag string (e.g.,"div"), plus an internal flag__styledComponentto identify it as a styled component. - Styled components built from custom React components (e.g.,
styled(ReactComponent)) have atargetproperty pointing to the original custom component function/class.
- Styled components built from native tags (e.g.,
The isReactComponent Implementation
Putting this together, here's a function that covers all your example cases:
import React from 'react'; function isReactComponent(element) { // First, confirm we're dealing with a valid React element if (!React.isValidElement(element)) { // Adjust this if you need to handle non-element inputs, but per your examples, this is safe return false; } const elementType = element.type; // 1. Native HTML element (allowed) if (typeof elementType === 'string') { return false; } // 2. Check if it's a styled-component if (elementType.__styledComponent) { // Allow if the styled-component targets a native tag (string target) if (typeof elementType.target === 'string') { return false; } // Forbid if it targets a custom React component (function target) return typeof elementType.target === 'function'; } // 3. Regular custom React component (forbidden) return typeof elementType === 'function'; }
Testing Against Your Examples
Let's verify this works with all your test cases:
<SophisticatedComponent element={<ReactComponent/>}/>:element.typeis theReactComponentfunction, not a styled-component → returnstrue→ throws error (correct).<SophisticatedComponent element={<div><ReactComponent/></div>}/>:element.typeis"div"(string) → returnsfalse→ allowed (correct).<SophisticatedComponent element={<StyledComponent><ReactComponent/></StyledComponent>}/>:StyledComponenthas__styledComponentflag andtarget: "div"→ returnsfalse→ allowed (correct).<SophisticatedComponent element={<StyledReactComponent/>}/>:StyledReactComponenthas__styledComponentflag andtarget: ReactComponent(function) → returnstrue→ throws error (correct).
Notes for Edge Cases
- Memoized Components: If you need to handle memoized components (e.g.,
React.memo(ReactComponent)), you'll need to add a check to unwrap the memo wrapper. You can modify the function to recursively checkelementType.typeuntil you find a non-memo component. - Styled-Components Internal Properties: The
__styledComponentflag is an internal property of styled-components, but it's been stable across versions. If you want to avoid relying on internal properties, you could check ifelementType.displayNamestarts with "Styled", but this is less reliable (since display names can be customized).
内容的提问来源于stack exchange,提问作者mqklin
相关产品推荐
相关产品推荐

