This error occurs when React.lazy() receives a factory function that doesn't resolve to a valid React function component. The import must have a default export that is a functional component, class component, or memo/forwardRef wrapper.
Fixes React.lazy: the factory function must be a function component
// ✓ Correct
function MyComponent() {
return <div>Hello</div>;
}
export default MyComponent;
// ✗ Wrong - no default export
export function MyComponent() {
return <div>Hello</div>;
}// ✓ Correctfunction MyComponent() {return <div>Hello</div>;}export default MyComponent;// ✗ Wrong - no default exportexport function MyComponent() {return <div>Hello</div>;}React.lazy: the factory function must be a function component
React.lazy() is used for code-splitting and dynamic imports of React components. It expects a factory function that returns a Promise resolving to a module with a default export containing a valid React component. If the factory doesn't resolve to a function or class component, React throws this error.
Ensure the lazy-loaded component file exports a valid React component as default.
// ✓ Correct
function MyComponent() {
return <div>Hello</div>;
}
export default MyComponent;
// ✗ Wrong - no default export
export function MyComponent() {
return <div>Hello</div>;
}React.lazy() expects a factory function, not the import result directly. The factory must return a Promise.
// ✓ Correct
const MyComponent = React.lazy(() => import('./MyComponent'));
// ✗ Wrong - passing import directly
const MyComponent = React.lazy(import('./MyComponent'));React.lazy only works with default exports. If your component uses named exports, convert it to a default export:
// MyComponent.jsx - before
export function MyComponent() {
return <div>Content</div>;
}
// MyComponent.jsx - after
function MyComponent() {
return <div>Content</div>;
}
export default MyComponent;If you can't change the original component's export, create a wrapper module:
// MyComponent.jsx (original - uses named export)
export function MyComponent() {
return <div>Content</div>;
}
// MyComponent.lazy.js (wrapper)
export { MyComponent as default } from './MyComponent';
// In your app
const MyComponent = React.lazy(() => import('./MyComponent.lazy'));Always wrap lazy components in a Suspense boundary with a fallback UI:
const MyComponent = React.lazy(() => import('./MyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<MyComponent />
</Suspense>
);
}Test that your import resolves correctly in the browser console:
// Check if the import resolves to a function/component
import('./MyComponent').then((module) => {
console.log(module.default); // Should be a function or class
console.log(typeof module.default); // Should be 'function'
});React.lazy() uses dynamic import() which is a runtime feature supported in modern bundlers (webpack, Vite, etc.). The factory function is called on-demand when the component is first rendered, not when the module loads. The Promise must resolve to an object with a .default property containing the actual component. This works with function components, class components, React.memo(), and React.forwardRef(). Do not use React.lazy() for class components at the top level without wrapping, though lazy-loaded class components themselves are valid. For error boundaries around lazy components, wrap the Suspense boundary in an Error Boundary component to gracefully handle loading failures.