This warning occurs when React receives an invalid component type, such as passing an object, undefined, or incorrect value where a React component is expected. It commonly happens due to import/export mismatches or incorrect prop types.
This React warning indicates that the component type being rendered or passed as a prop is not what React expects. React components must be either: 1. Built-in components (represented as strings like "div", "span", "button") 2. Function components (JavaScript functions that return JSX) 3. Class components (ES6 classes extending React.Component) When React encounters something else—such as an object, undefined, null, or a module object—it throws this warning because it cannot render the invalid type. This often manifests when there's a mismatch between how a component is exported and how it's imported, or when a prop that expects a component receives the wrong type. The warning typically includes details about what type was received (object, undefined, etc.) versus what was expected, which helps identify the source of the mismatch.
Verify that your imports match how the component is exported.
If the component is exported as a default export:
// ComponentA.js
export default function ComponentA() {
return <div>A</div>;
}
// Correct import
import ComponentA from './ComponentA';
// Incorrect import (will import module object)
import { ComponentA } from './ComponentA'; // Wrong!If the component is a named export:
// ComponentB.js
export function ComponentB() {
return <div>B</div>;
}
// Correct import
import { ComponentB } from './ComponentB';
// Incorrect import (will be undefined)
import ComponentB from './ComponentB'; // Wrong!Ensure the component file actually exports the component.
Common mistake - forgetting to export:
// MyComponent.js - WRONG
function MyComponent() {
return <div>Hello</div>;
}
// Missing export!Correct approach:
// MyComponent.js - CORRECT
export default function MyComponent() {
return <div>Hello</div>;
}
// Or as named export
export function MyComponent() {
return <div>Hello</div>;
}When passing components as props, ensure you're passing the component itself, not an instance or undefined.
Incorrect - passing undefined or wrong type:
// Wrong - component might be undefined
import { NonExistentComponent } from './components';
function Wrapper() {
return <Layout sidebar={NonExistentComponent} />; // undefined
}Correct approach:
import { Sidebar } from './components';
function Wrapper() {
// Pass the component reference, not an instance
return <Layout sidebar={Sidebar} />;
}
// In Layout component
function Layout({ sidebar: SidebarComponent }) {
return (
<div>
<SidebarComponent /> {/* Render as component */}
</div>
);
}Add PropTypes validation:
import PropTypes from 'prop-types';
Layout.propTypes = {
sidebar: PropTypes.elementType.isRequired,
};Ensure React.lazy() is used correctly with dynamic imports.
Incorrect lazy loading:
// Wrong - importing synchronously
const LazyComponent = React.lazy(() => import('./Component'));Correct lazy loading with default exports:
// Component must be default export
const LazyComponent = React.lazy(() => import('./Component'));
// Usage with Suspense
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}For named exports, wrap in default export:
// If component is named export
const LazyComponent = React.lazy(() =>
import('./Component').then(module => ({
default: module.NamedComponent
}))
);Circular imports can cause components to be undefined at runtime.
Identify circular dependencies:
# Install madge to detect circular dependencies
npm install --save-dev madge
# Check for circular dependencies
npx madge --circular src/Break the circular dependency:
// Before (circular):
// ComponentA.js imports ComponentB
// ComponentB.js imports ComponentA
// After (fixed):
// Extract shared logic to a new file
// SharedUtils.js - contains shared code
// ComponentA.js imports SharedUtils
// ComponentB.js imports SharedUtilsUse dependency injection or composition to avoid circular refs:
// Instead of direct import, pass as prop
function ParentComponent() {
return (
<ComponentA childComponent={ComponentB} />
);
}Check that your bundler is correctly resolving modules.
For Webpack/Create React App, check your import paths:
// Use full relative paths
import Component from './Component'; // ✓
import Component from './Component.jsx'; // ✓
import Component from './components'; // Only if index.js existsVerify your tsconfig.json or jsconfig.json:
{
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
}
}Clear build cache if issues persist:
# Create React App
rm -rf node_modules/.cache
# Next.js
rm -rf .next
# Vite
rm -rf node_modules/.vite
# Rebuild
npm install
npm run buildTypeScript Component Types
When using TypeScript, properly type component props:
import { ComponentType, FC } from 'react';
interface LayoutProps {
sidebar: ComponentType; // Accepts any valid component
header: ComponentType<{ title: string }>; // With specific props
}
const Layout: FC<LayoutProps> = ({ sidebar: Sidebar, header: Header }) => (
<div>
<Header title="My App" />
<Sidebar />
</div>
);React.ElementType vs ComponentType
- React.ElementType: Accepts strings (HTML tags) or components
- React.ComponentType: Only accepts function/class components
type ElementType = string | ComponentType; // "div" or MyComponent
type ComponentType<P = any> = ComponentClass<P> | FunctionComponent<P>;HOC (Higher-Order Component) Patterns
When wrapping components, preserve component type:
function withAuth<P extends object>(
Component: ComponentType<P>
): ComponentType<P> {
return (props: P) => {
const isAuthenticated = useAuth();
if (!isAuthenticated) return <LoginScreen />;
return <Component {...props} />;
};
}Production vs Development Differences
Component type errors may only appear in production if:
- Tree shaking removes unused exports
- Minification changes module structure
- Dynamic imports behave differently
Always test production builds locally:
npm run build
npx serve -s build # For CRA
npm run preview # For ViteReact Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite