This error occurs when you render a component created with React.lazy() without wrapping it in a Suspense boundary. React.lazy defers loading component code until it's needed, but while the code is loading, the component "suspends". Without Suspense to handle this suspended state, React throws an error. Wrapping the lazy component in a Suspense boundary with a fallback UI fixes the issue.
When you use React.lazy() to dynamically import a component, React delays loading that component's code until it's rendered. While the code is being fetched over the network, the component is in a "suspended" state. React requires you to wrap suspended components in a <Suspense> boundary, which provides a fallback UI (like a loading spinner) to show while the code loads. If you try to render a lazy component without Suspense, React has no way to handle the suspended state and throws this error. The Suspense boundary tells React: "I know this component might take time to load, and here's what to show in the meantime."
Find the place where you created the lazy component using React.lazy(). Look for patterns like:
const LazyComponent = React.lazy(() => import('./MyComponent'));Then find where you're trying to render it (likely in JSX as <LazyComponent />).
Surround the lazy component with a <Suspense> boundary. The Suspense component requires a fallback prop that specifies what to render while the code is loading.
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./MyComponent'));
export function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}The fallback can be any React element: a loading spinner, text, a skeleton screen, or a placeholder UI.
Instead of just showing "Loading...", consider creating a reusable loading component that matches your app's design:
function LoadingSpinner() {
return (
<div style={{ display: 'flex', justifyContent: 'center', padding: '20px' }}>
<div>Loading component...</div>
</div>
);
}
export function App() {
const LazyComponent = React.lazy(() => import('./MyComponent'));
return (
<Suspense fallback={<LoadingSpinner />}>
<LazyComponent />
</Suspense>
);
}If the lazy component code fails to load (network error, syntax error, etc.), React will throw an error. Wrap your Suspense boundary in an Error Boundary to gracefully handle load failures:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <div>Failed to load component. Please refresh the page.</div>;
}
return this.props.children;
}
}
export function App() {
const LazyComponent = React.lazy(() => import('./MyComponent'));
return (
<ErrorBoundary>
<Suspense fallback={<LoadingSpinner />}>
<LazyComponent />
</Suspense>
</ErrorBoundary>
);
}Test your lazy-loaded component:
1. Open browser DevTools (F12) and go to the Network tab
2. Filter by "JS" or "XHR" to see network requests
3. Load your page and watch for the lazy component's chunk being downloaded
4. You should briefly see your fallback UI (loading indicator)
5. Once loaded, the actual component should render
If you see the error message still appearing, verify that the Suspense boundary is correctly wrapping the lazy component and that no parent component is removing it.
Ensure your Suspense wrapper is always present during render. A common mistake is conditionally rendering the Suspense:
// WRONG - Suspense might not be rendered
function App({ showLazy }) {
return (
showLazy && <Suspense fallback={<div>Loading</div>}>
<LazyComponent />
</Suspense>
);
}
// CORRECT - Suspense is always present, but its child might not be
function App({ showLazy }) {
return (
<Suspense fallback={<div>Loading</div>}>
{showLazy && <LazyComponent />}
</Suspense>
);
}React.lazy() uses dynamic imports under the hood, which means the lazy component's code is split into a separate JavaScript chunk. This chunk is only downloaded when the component is first rendered, enabling code-splitting and faster initial page loads. Suspense is required because the component code might not be available immediately. In Next.js and other meta-frameworks, Suspense has special handling for server-side rendering (SSR). Be aware that Suspense on the server requires the component code to be available at build time, so truly async data loading in lazy components may need special handling. For complex scenarios with multiple lazy components, you can nest multiple Suspense boundaries to show different loading states for different parts of your UI. If a lazy component fails to load due to a network error, the Error Boundary (not Suspense) will catch that error. For production applications, consider using a library like @loadable/components if you need more control over code-splitting without the Suspense requirement, though this is rarely necessary with modern React.
Prop spreading could cause security issues
Prop spreading could cause security issues
Error: error:0308010C:digital envelope routines::unsupported
Error: error:0308010C:digital envelope routines::unsupported
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.
React Hook useEffect placed inside a condition
Hook can only be called inside the body of a function component
Hook can only be called inside the body of a function component
Rollup failed to resolve import during build
How to fix "Rollup failed to resolve import" in React