is-react-comp
v1.0.3
Published
    - ✅ Components wrapped in
forwardRef() - ✅ Lazy-loaded components
- ✅ React elements (optional)
Quick Start
Install it
npm install is-react-comp
# yarn
yarn add is-react-comp
# pnpm
pnpm add is-react-comp
# bun
bun add is-react-compUse it
import { isReactComponent } from 'is-react-comp';
function MyComponent() {
return <div>Hello!</div>;
}
// Check if it's a React component
if (isReactComponent(MyComponent)) {
console.log('Yep, this is a React component! 🎉');
}
// Works with regular variables too
const something = getSomethingFromSomewhere();
if (isReactComponent(something)) {
// It's safe to render it
return <something />;
}What else can you do?
Get info about a component
import { getReactComponentInfo } from 'is-react-comp';
const info = getReactComponentInfo(MyComponent);
console.log(info.componentType); // "function", "class", "memo", etc.
console.log(info.displayName); // "MyComponent"Check for specific types
import {
isFunctionComponent,
isClassComponent,
isMemoComponent
} from 'is-react-comp';
if (isFunctionComponent(MyComponent)) {
console.log('This is a function component');
}Use in React components
import { useIsComponent } from 'is-react-comp';
function MyWrapper({ children }) {
const { isComponent } = useIsComponent(children);
if (!isComponent) {
return <div>Not a valid component!</div>;
}
return children;
}Complete Examples
Function Component
import { isReactComponent, isFunctionComponent } from 'is-react-comp';
function MyButton({ text }) {
return <button>{text}</button>;
}
console.log(isReactComponent(MyButton)); // true
console.log(isFunctionComponent(MyButton)); // trueClass Component
import { isReactComponent, isClassComponent } from 'is-react-comp';
class MyCounter extends React.Component {
render() {
return <div>Count: {this.props.count}</div>;
}
}
console.log(isReactComponent(MyCounter)); // true
console.log(isClassComponent(MyCounter)); // trueMemo Component
import { isReactComponent, isMemoComponent } from 'is-react-comp';
const ExpensiveComponent = React.memo(function({ data }) {
return <div>{data.map(item => <span key={item.id}>{item.name}</span>)}</div>;
});
console.log(isReactComponent(ExpensiveComponent)); // true
console.log(isMemoComponent(ExpensiveComponent)); // trueForwardRef Component
import { isReactComponent, isForwardRefComponent } from 'is-react-comp';
const MyInput = React.forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
console.log(isReactComponent(MyInput)); // true
console.log(isForwardRefComponent(MyInput)); // trueLazy Component
import { isReactComponent, isLazyComponent } from 'is-react-comp';
const LazyComponent = React.lazy(() => import('./MyComponent'));
console.log(isReactComponent(LazyComponent)); // true
console.log(isLazyComponent(LazyComponent)); // trueReact Elements
import { isReactComponent, isReactElement } from 'is-react-comp';
const element = <div>Hello World</div>;
const component = function() { return <div>Hello</div>; };
console.log(isReactElement(element)); // true
console.log(isReactElement(component)); // false
// Include elements in component check
console.log(isReactComponent(element, { includeElements: true })); // true
console.log(isReactComponent(component, { includeElements: true })); // trueReal-World Plugin System Example
import { isReactComponent, getReactComponentInfo } from 'is-react-comp';
function PluginRenderer({ plugins }) {
return plugins.map((plugin, index) => {
// Validate each plugin is a React component
if (!isReactComponent(plugin.component)) {
console.error(`Plugin ${index} is not a valid React component`);
return <div key={index}>Invalid plugin component</div>;
}
const info = getReactComponentInfo(plugin.component);
return (
<div key={index}>
<h3>{plugin.name}</h3>
<p>Type: {info.componentType}</p>
<plugin.component {...plugin.props} />
</div>
);
});
}
// Usage
const plugins = [
{
name: 'Header',
component: () => <header>My App</header>,
props: {}
},
{
name: 'Footer',
component: React.memo(() => <footer>© 2024</footer>),
props: {}
}
];
<PluginRenderer plugins={plugins} />Component Validation with Fallback
import { withComponentValidation } from 'is-react-comp';
// Your regular component
function UserProfile({ user }) {
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
// Wrap with validation and fallback
const SafeUserProfile = withComponentValidation(UserProfile, {
fallback: <div className="error">Failed to load user profile</div>,
strict: true
});
// Usage - will show fallback if UserProfile is invalid
function App({ profileComponent }) {
return <SafeUserProfile user={{ name: 'John', email: '[email protected]' }} />;
}
// Dynamic component example
function DynamicComponentLoader({ component, fallback }) {
const SafeComponent = withComponentValidation(component, {
fallback: fallback || <div>Component not available</div>
});
return <SafeComponent />;
}
// Usage with potentially invalid component
const maybeInvalid = null; // Could be anything
<DynamicComponentLoader
component={maybeInvalid}
fallback={<div className="loading-error">Component failed to load</div>}
/>Advanced Fallback Examples
import { withComponentValidation } from 'is-react-comp';
// Custom fallback component
function ErrorFallback({ error, componentName }) {
return (
<div className="component-error">
<h3>⚠️ Component Error</h3>
<p>Failed to render: {componentName}</p>
{error && <p>Error: {error.message}</p>}
</div>
);
}
// Loading fallback
function LoadingFallback() {
return (
<div className="loading">
<div className="spinner"></div>
<p>Loading component...</p>
</div>
);
}
// Wrap components with different fallbacks
const SafeHeader = withComponentValidation(HeaderComponent, {
fallback: <ErrorFallback componentName="Header" />
});
const SafeLazyComponent = withComponentValidation(LazyComponent, {
fallback: <LoadingFallback />
});
// Conditional fallback based on component type
function smartFallback(component) {
const info = getReactComponentInfo(component);
if (info.componentType === 'lazy') {
return <LoadingFallback />;
} else {
return <ErrorFallback componentName={info.displayName || 'Unknown'} />;
}
}
const SmartSafeComponent = withComponentValidation(SomeComponent, {
fallback: smartFallback(SomeComponent)
});Why would you need this?
- Plugin systems: When users can pass in custom components
- Dynamic rendering: When you're not sure what you're getting
- Debugging: To figure out what type of component you're working with
- Component libraries: To validate user input
Options
You can customize how it works:
// Include React elements as components too
isReactComponent(something, { includeElements: true });
// Less strict checking (might have false positives)
isReactComponent(something, { strict: false });TypeScript Support
If you're using TypeScript, you get automatic type checking:
import { isReactComponent } from 'is-react-comp';
function doSomething(value: unknown) {
if (isReactComponent(value)) {
// TypeScript now knows this is a React component!
return <value />;
}
}That's it!
No complicated setup, no weird dependencies. Just a simple tool that does one thing well.
Questions? Open an issue
License
MIT © Nikhil Kumar
