2021-05-10 07:22:15
在 React 中,Suspense 可通过包裹异步组件或数据获取操作,在加载期间显示占位符 UI,从而改进异步渲染的流畅性和用户体验。 以下是具体实现方法、场景及最佳实践:
一、核心功能与工作原理组件加载:与 React.lazy 动态导入结合,实现代码分割。
数据获取:与 React Query、Relay 或自定义数据获取库(实验性)集成。
并发模式:优化渲染性能,避免阻塞主线程。
问题:同步加载大组件(如 HeavyComponent)会增加初始包大小,延长加载时间。解决方案:使用 React.lazy + Suspense 实现按需加载。
import React, { Suspense } from "react";const HeavyComponent = React.lazy(() => import("./HeavyComponent"));function App() { return ( <div> <h1>主应用</h1> <Suspense fallback={<div>加载 HeavyComponent...</div>}> <HeavyComponent /> </Suspense> </div> );}效果:HeavyComponent 仅在渲染时加载,加载期间显示占位符。
2. 多个延迟加载组件场景:同时加载多个动态组件时,需统一处理加载状态。实现:用单个 Suspense 包裹多个组件,占位符会持续显示直到所有组件加载完成。
const ComponentA = React.lazy(() => import("./ComponentA"));const ComponentB = React.lazy(() => import("./ComponentB"));function App() { return ( <div> <Suspense fallback={<div>加载组件中...</div>}> <ComponentA /> <ComponentB /> </Suspense> </div> );}3. 数据获取(实验性)场景:结合 React Query 或 Relay,在数据加载期间显示占位符。示例(需库支持):
import { useQuery } from "react-query";function DataComponent() { const { data, isLoading } = useQuery("key", fetchData); if (isLoading) return <div>加载数据中...</div>; // 传统方式 // 实验性 Suspense 集成(需配置库支持 Suspense) return <div>{data}</div>;}function App() { return ( <Suspense fallback={<div>全局加载中...</div>}> <DataComponent /> </Suspense> );}三、错误处理:结合错误边界Suspense 不处理加载失败,需通过错误边界(Error Boundary)捕获异常:
class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError() { return { hasError: true }; } componentDidCatch(error) { console.error("Error:", error); } render() { return this.state.hasError ? <div>加载失败</div> : this.props.children; }}function App() { return ( <ErrorBoundary> <Suspense fallback={<div>加载中...</div>}> <LazyComponent /> </Suspense> </ErrorBoundary> );}四、最佳实践用户体验:避免空白页面,保持应用响应。
性能优化:代码分割减少初始包大小。
代码简洁:声明式管理加载状态,减少样板代码。
数据获取:Suspense 对数据加载的支持仍为实验性,需依赖特定库。
浏览器兼容性:需支持 ES6 模块和 Promise。
错误处理:必须手动添加错误边界。
React Suspense 通过声明式占位符和自动状态切换,显著简化了异步渲染逻辑。结合 React.lazy、错误边界和并发模式,可构建更流畅、高效的应用。对于数据获取,建议优先使用稳定库(如 React Query),并关注 Suspense 的后续官方支持进展。