How to fix React.lazy: expected to receive a function component in React

ReactINTERMEDIATEHIGHUpdated Dec 10, 2025· 159 views

This error occurs when React.lazy receives an invalid component instead of a Promise that resolves to a function component. Common causes include missing default exports, returning objects instead of components, or incorrect import syntax. The fix involves ensuring the lazily-loaded module exports a valid React component as its default export.

Quick fix

Fixes React.lazy: expected to receive a function component

// ✓ Correct: default export of component
export default function MyComponent() {
  return <div>Hello</div>;
}

// ✓ Correct: named export reassigned as default
function MyComponent() {
  return <div>Hello</div>;
}
export default MyComponent;

// ✗ Wrong: named export only
export function MyComponent() {
  return <div>Hello</div>;
}

// ✗ Wrong: exports object or other value
export default { component: MyComponent };
  1. Verify the component exports as default export
  2. Check the import path in React.lazy
  3. Handle named exports with lazy loading
  4. Verify the component is a valid React component
react — error
// ✓ Correct: default export of component
export default function MyComponent() {
return <div>Hello</div>;
}
// ✓ Correct: named export reassigned as default
function MyComponent() {
return <div>Hello</div>;
}
export default MyComponent;
// ✗ Wrong: named export only
export function MyComponent() {
return <div>Hello</div>;
}
// ✗ Wrong: exports object or other value
export default { component: MyComponent };
React.lazy: expected to receive a function component

What this error means

React.lazy is designed to dynamically import and load React components on-demand. It expects a function that returns a Promise (typically from a dynamic import statement) that resolves to a module with a valid React component as its default export. When React.lazy receives something that doesn't resolve to a valid component—such as an object, a plain function, a named export, or a non-component value—it throws this error. The component resolver sees that the resolved value is not a proper React component type (a function, memo, or forwardRef wrapper). The error prevents the lazy-loaded component from being rendered because React cannot determine how to display something that isn't a recognized component.

Typical symptoms

  • Error message: "React.lazy: expected to receive a function component"
  • Application crashes when the lazy component tries to render
  • Error appears in console during component mounting or when navigating to the lazy component route
  • Suspense fallback never shows because the error is thrown before component loads
  • Error appears immediately if the dynamic import is invalid, or after the import resolves if the resolved value is incorrect
  • Runtime error prevents the entire component tree from rendering below the Suspense boundary

Common causes

  1. Importing a named export instead of a default export from the module
  2. Module exports an object, function, or value that is not a valid React component
  3. Dynamic import path is incorrect or points to a non-existent file
  4. Component file is missing an export statement or exports undefined as default
  5. Passing a non-function to React.lazy (should be a function that returns a Promise)
  6. Circular dependency in the lazily-loaded module preventing proper export
  7. Module is a CommonJS export without a proper default property
  8. Using React.lazy with a component that has been instantiated (e.g., <MyComponent /> instead of MyComponent)

How to fix "React.lazy: expected to receive a function component"

1Verify the component exports as default export

React.lazy requires the lazily-loaded module to export a React component as its default export:

tsx
// ✓ Correct: default export of component
export default function MyComponent() {
  return <div>Hello</div>;
}

// ✓ Correct: named export reassigned as default
function MyComponent() {
  return <div>Hello</div>;
}
export default MyComponent;

// ✗ Wrong: named export only
export function MyComponent() {
  return <div>Hello</div>;
}

// ✗ Wrong: exports object or other value
export default { component: MyComponent };

Ensure the component file uses one of the correct patterns with a default export.

2Check the import path in React.lazy

Verify that the dynamic import path is correct and points to the component file:

tsx
import { lazy, Suspense } from 'react';

// ✓ Correct: relative path to component file
const MyComponent = lazy(() => import('./components/MyComponent'));

// ✓ Correct: path to directory with index.tsx
const Dashboard = lazy(() => import('./pages/Dashboard'));

// ✗ Wrong: path to non-existent file
const BadComponent = lazy(() => import('./BadPath/Component'));

// ✗ Wrong: importing an object or non-component
const NotComponent = lazy(() => import('./utils/helpers'));

Double-check that the path resolves to an actual component file and that the file exists.

3Handle named exports with lazy loading

If you need to lazy-load a named export, wrap it in an intermediate function:

tsx
import { lazy } from 'react';

// Component with named export
// components/MyComponent.tsx
export function MyComponent() {
  return <div>Hello</div>;
}

// Wrap named export in default export at import time
const MyComponent = lazy(() =>
  import('./components/MyComponent').then(module => ({
    default: module.MyComponent
  }))
);

This pattern converts the named export to a default export that React.lazy can use.

4Verify the component is a valid React component

Ensure the imported module contains an actual React component, not just utilities or helper functions:

tsx
import { lazy } from 'react';

// ✓ Correct: actual React component
// pages/Dashboard.tsx
export default function Dashboard() {
  return <main>Dashboard</main>;
}

// ✗ Wrong: helper function, not a component
// utils/helper.ts
export default function formatDate(date) {
  return date.toLocaleDateString();
}

// If lazy()'ing the helper:
const Dashboard = lazy(() => import('./pages/Dashboard')); // OK
const Helper = lazy(() => import('./utils/helper')); // ERROR

Make sure you're lazily loading actual React components, not utility functions.

5Ensure React.lazy receives a function, not a Promise

React.lazy expects a function that returns a Promise, not a Promise directly:

tsx
import { lazy } from 'react';

// ✓ Correct: function returning Promise
const MyComponent = lazy(() => import('./MyComponent'));

// ✗ Wrong: direct Promise
const MyComponent = lazy(import('./MyComponent')); // ERROR

// ✗ Wrong: async function (returns Promise)
const MyComponent = lazy(async () => {
  return import('./MyComponent');
});

// ✓ Correct: async function with proper import
const MyComponent = lazy(() => import('./MyComponent'));

Pass a function to lazy(), not a Promise or direct import statement.

6Wrap lazy component in Suspense boundary

Always render lazy components inside a Suspense boundary with a fallback:

tsx
import { lazy, Suspense } from 'react';

const MyComponent = lazy(() => import('./MyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <MyComponent />
    </Suspense>
  );
}

The Suspense boundary handles the loading state and provides a fallback UI while the component is being imported. This also helps isolate errors if they occur.

7Add error boundary to catch component errors

Use an Error Boundary to gracefully handle errors during lazy loading:

tsx
import { lazy, Suspense, Component } from 'react';

const MyComponent = lazy(() => import('./MyComponent'));

class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    console.error('Lazy loading failed:', error);
  }

  render() {
    if (this.state.hasError) {
      return <div>Failed to load component</div>;
    }
    return this.props.children;
  }
}

function App() {
  return (
    <ErrorBoundary>
      <Suspense fallback={<div>Loading...</div>}>
        <MyComponent />
      </Suspense>
    </ErrorBoundary>
  );
}

Error Boundaries catch errors thrown during rendering, including lazy component loading failures.

8Test the lazy component in isolation

Create a simple test to verify the lazy component loads correctly:

tsx
import { lazy, Suspense } from 'react';
import { render, waitFor } from '@testing-library/react';

const MyComponent = lazy(() => import('./MyComponent'));

it('lazy loads the component', async () => {
  const { getByText } = render(
    <Suspense fallback={<div>Loading</div>}>
      <MyComponent />
    </Suspense>
  );

  // Wait for component to finish loading
  await waitFor(() => {
    expect(getByText('Expected content')).toBeInTheDocument();
  });
});

Testing in isolation helps identify whether the lazy load itself is the problem or if there's an issue with how the component renders.

Advanced notes

Webpack Chunk Names: For better debugging, add webpack comments to name your chunks:

tsx
const MyComponent = lazy(() =>
  import(/* webpackChunkName: "my-component" */ './MyComponent')
);

This makes it easier to identify which chunk failed in build tools and production monitoring.

Route-Based Code Splitting: A common pattern is lazy-loading route components:

tsx
import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Loading page...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

This reduces initial bundle size by splitting route components into separate chunks.

Preloading Lazy Components: Preload components before rendering to avoid loading delays:

tsx
const MyComponent = lazy(() => import('./MyComponent'));

// Preload before rendering
const preloadComponent = () => {
  import('./MyComponent');
};

// Use on hover or link focus
<Link to="/page" onMouseEnter={preloadComponent}>
  Go to page
</Link>

This can significantly improve perceived performance.

Race Conditions: Be aware of potential race conditions when using lazy with dynamic imports and state:

tsx
function App() {
  const [showComponent, setShowComponent] = useState(false);

  // Component changes dynamically based on state
  const Component = showComponent ? LazyA : LazyB;

  return <Component />;
}

Ensure your logic properly handles switching between different lazy components.

Frequently asked questions

What does "React.lazy: expected to receive a function component" mean?
lazy is designed to dynamically import and load React components on-demand. It expects a function that returns a Promise (typically from a dynamic import statement) that resolves to a module with a valid React component as its default export. lazy receives something that doesn't resolve to a valid component—such as an object, a plain function, a named export, or a non-component value—it throws this error.
How do I fix "React.lazy: expected to receive a function component"?
This error occurs when React.lazy receives an invalid component instead of a Promise that resolves to a function component. Common causes include missing default exports, returning objects instead of components, or incorrect import syntax. The fix involves ensuring the lazily-loaded module exports a valid React component as its default export.
What causes "React.lazy: expected to receive a function component"?
Importing a named export instead of a default export from the module Module exports an object, function, or value that is not a valid React component Dynamic import path is incorrect or points to a non-existent file
Is the "React.lazy: expected to receive a function component" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading