基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

React.lazy 和 Suspense 的用法

知识点图片

在 React 中,React.lazySuspense 是用于实现代码分割(Code Splitting)懒加载组件的重要特性。它们可以帮助你将大型应用拆分成更小的代码块,按需加载,从而提升初始加载性能。


一、React.lazy

✅ 作用

React.lazy() 允许你将一个动态导入的组件渲染为一个常规的 React 组件。它使得组件的代码可以在需要时才被加载(即懒加载)。

📌 语法

jsx
const LazyComponent = React.lazy(() => import('./LazyComponent'));
  • import('./LazyComponent'):返回一个 Promise,当模块加载完成时解析。
  • React.lazy() 会等待这个 Promise resolve,然后渲染导出的默认组件。

⚠️ 注意:被 lazy() 包装的组件必须有一个 默认导出(default export)。


二、Suspense

✅ 作用

由于 React.lazy() 是异步加载组件的,Suspense 用于在等待懒加载组件完成渲染时显示一个“备用内容”(如 loading spinner)。

📌 语法

jsx
<Suspense fallback={<Loading />}>
  <LazyComponent />
</Suspense>
  • fallback:当懒加载组件还在加载中时显示的内容(可以是任意 React 元素)。
  • <Suspense> 只能包裹一个子节点,但可以用 Fragment <>...</>

三、完整示例

jsx
import React, { Suspense } from 'react';

// 👇 lazy load the component
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <div>
      <h1>My App</h1>

      {/* 👇 Use Suspense to show a fallback while loading */}
      <Suspense fallback={<div>Loading...</div>}>
        <HeavyComponent />
      </Suspense>
    </div>
  );
}

export default App;

对应的 ./HeavyComponent.jsx(必须有默认导出):

jsx
// HeavyComponent.jsx
import React from 'react';

const HeavyComponent = () => {
  return (
    <div style={{ padding: '20px', background: '#f0f0f0' }}>
      This is a heavy component loaded lazily!
    </div>
  );
};

export default HeavyComponent; // ✅ must be default export

四、多个懒加载组件 + Suspense

你可以将多个懒加载组件放在同一个 <Suspense> 下:

jsx
<Suspense fallback={<LoadingSpinner />}>
   <Header />
   <MainContent />
   <Sidebar />
</Suspense>

如果其中任何一个子组件是懒加载的且未就绪,整个区域都会显示 fallback


##五、错误处理(配合 Error Boundary)

由于网络问题可能导致模块加载失败,建议结合 Error Boundary使用:

jsx
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 <h2>Something went wrong.</h2>;
     }
     return this.props.children; 
   }
}

// Usage:
<ErrorBoundary>
   <Suspense fallback={<Loading />}>
     <LazyComponent />
   </Suspense>
</ErrorBoundary>

这样即使懒加载失败也不会白屏崩溃。


##六、服务端渲染(SSR)注意事项

⚠️ React.lazy 不支持服务端渲染。如果你需要做 SSR,可以考虑使用第三方库如 @loadable/component


##七、命名导出怎么办?

如果模块是命名导出(export const MyComp),不能直接用 lazy,需包装一下:

jsx
const NamedExportedComp = React.lazy(() =>
 import('./SomeModule').then(module => ({
    default: module.NamedExportedComp,
 }))
);

或者更简洁地写成:

plaintext
 const mod = await import('./SomeModule'); // Assume named export is "NamedExportedComp"
return { default: mod.NamedExportedComp };
});

##总结:关键点回顾

Feature Description
React.lazy(fn) fn returns a dynamic import (Promise), used for code splitting.
Requires Default export in the imported module.
<Suspense> Shows fallback UI while waiting for lazy components.
Multiple lazy components Can be wrapped together under one Suspense.
Error handling Use Error Boundary to catch loading failures.
Not SSR-friendly Avoid with Next.js server-side rendering unless using alternatives like @loadable.

通过合理使用 React.lazy + Suspense,可以显著提升大型应用的性能和用户体验。

00:00
00:00