React Suspense 和并发模式——异步渲染的未来

6 阅读5分钟

React 16.8 及更高版本中引入的 Suspense 和 Concurrent 模式旨在提升用户体验和性能,尤其是在异步数据加载和动画方面。它们是 React 下一代渲染策略的一部分,旨在提供更流畅的交互和更高效的资源调度。

悬念 Suspense是一个允许你指定组件异步加载区域的组件。当这些组件的数据尚未准备好时,Suspense会显示一个占位符(回退),直到​​数据可用,然后渲染组件。以下是一个简单的示例:

目的 Suspense 主要解决组件渲染过程中的异步数据加载,使组件能够等待其依赖项准备就绪后再进行渲染,而不是显示不完整的占位符或错误消息。

工作原理 异步边界:Suspense组件充当边界,包装可能需要等待数据加载的子组件。 后备 UI:在等待期间,Suspense 使用fallbackprop 来显示加载指示器或其他占位符内容。 数据预加载:结合React.lazy,它可以实现组件的延迟加载,在第一次渲染时自动触发其加载。 数据加载协调:与 React 的 Context API 和钩子(例如useSuspenseResource)配对,它提供了对数据加载的细粒度控制。 import React, { useState, useEffect, lazy, Suspense } from 'react'; import { fetchSomeData } from './asyncDataFetch'; // Asynchronous data fetch function

const AsyncComponent = lazy(() => { return new Promise((resolve) => { fetchSomeData().then(() => resolve(import('./AsyncComponent'))); }); });

function App() { const [dataReady, setDataReady] = useState(false);

useEffect(() => { fetchSomeData().then(() => setDataReady(true)); }, []);

return (

{dataReady ? ( <Suspense fallback={
Loading...
}> ) : null}
); }

export default App; 在此代码中,AsyncComponent是延迟加载的。它仅在fetchSomeData完成并dataReady设置为时渲染true;否则,会显示“正在加载...”占位符。

并发模式 Concurrent Mode是一种渲染策略,允许 React 在不中断用户界面的情况下暂停和恢复渲染。通过智能调度任务,它可以优化用户体验,例如在用户交互(例如滚动)期间暂停后台内容加载,以优先渲染可见部分。

目的 Concurrent 模式通过并发渲染和智能调度增强了应用程序的响应速度和交互流畅度。它允许 React 高效地利用空闲时间进行 UI 更新,同时确保高优先级任务的即时响应。

核心概念 并发渲染:允许多个渲染任务同时运行,允许 React 暂停低优先级渲染以进行用户输入或高优先级更新。 时间分片:将复杂的渲染任务分解成更小的块,逐步执行以避免阻塞主线程。 优先级调度:React 根据任务紧急程度(例如,用户交互)分配渲染优先级。 import React, { useState, useEffect, startTransition } from 'react';

function MyComponent() { const [value, setValue] = useState(0);

useEffect(() => { startTransition(() => { // Code here runs in a concurrent task, not blocking UI updates setValue(value + 1); }); }, [value]);

return

{value}
; }

export default MyComponent; 在此示例中,startTransition将代码放在低优先级任务中,确保即使执行需要时间,它也不会阻止正在进行的 UI 更新。

结合 Suspense 和 Concurrent 模式 Suspense并且Concurrent Mode经常一起使用来创建更流畅的应用程序体验,允许异步操作在不中断 UI 的情况下进行。

import React, { useState, useEffect, startTransition, lazy, Suspense } from 'react'; import { fetchSomeData } from './asyncDataFetch'; // Asynchronous data fetch function

const AsyncComponent = lazy(() => { return new Promise((resolve) => { fetchSomeData().then(() => resolve(import('./AsyncComponent'))); }); });

function App() { const [dataReady, setDataReady] = useState(false);

useEffect(() => { startTransition(() => { fetchSomeData().then(() => setDataReady(true)); }); }, []);

return (

{dataReady ? ( <Suspense fallback={
Loading...
}> ) : null}
); }

export default App; startTransition确保数据加载不会阻塞 UI,同时Suspense显示加载指示器直至数据准备就绪。两者结合,即使在异步数据和组件加载期间也能提供无缝的用户体验。

实际好处 1.高效的资源加载和渲染 延迟加载:使用React.lazy和Suspense,组件可以按需加载,减少初始加载时间并改善用户体验。 数据预加载:在用户到达页面或状态之前预加载数据,最大限度地减少交互期间的等待时间。 2. 优雅的错误处理 统一错误显示:将错误边界与 Suspense 的错误处理相结合,以一致地管理组件加载或数据提取期间的错误。 3. 动态优先级调整 自适应用户体验:并发模式允许 React 根据运行时环境(例如,设备性能、用户交互状态)调整渲染任务优先级,以获得最佳性能。 4.简化状态管理 与状态库的无缝集成:与 MobX、Redux 或 React 的 Context API 一起使用时,Suspense 和 Concurrent Mode 简化了异步状态更新,降低了同步复杂性。 5.未来的可扩展性 框架级支持:随着 React 的发展,Suspense 和 Concurrent Mode 将释放更多潜力,例如改进对服务器端渲染 (SSR) 和客户端渲染 (CSR) 的支持,以及用于灵活渲染逻辑控制的更广泛的 API 集。 Suspense 和并发模式的完整示例 安装所需的库 npm install axios react-spring react-dom 创建一个简单的组件,在数据加载后显示动画:

import React, { lazy, Suspense, useState, useEffect } from 'react'; import { useSpring, animated } from 'react-spring'; import axios from 'axios';

const LazyAnimatedComponent = lazy(() => { return new Promise(resolve => { setTimeout(() => { resolve(import('./LazyAnimatedComponent')); }, 2000); // Simulate async loading delay }); });

function App() { const [isLoaded, setIsLoaded] = useState(false); const fadeInProps = useSpring({ opacity: isLoaded ? 1 : 0 });

useEffect(() => { axios.get('api.example.com/data').then… => { setIsLoaded(true); }); }, []);

return (

<Suspense fallback={
Loading...
}> <animated.div style={fadeInProps}> </animated.div>
); }

export default App; 在 中LazyAnimatedComponent添加动画效果,例如淡入www.mytiesarongs.com

import React from 'react'; import { animated, useSpring } from 'react spring';

function LazyAnimatedComponent() { const fadeInProps = useSpring({ opacity: 1 });

return ( <animated.div style={fadeInProps}>

Hello, World!

This is an animated lazy-loaded component.

</animated.div> ); }

export default LazyAnimatedComponent; 要充分利用Concurrent Mode,请在 ReactDOM 渲染方法中启用它,通常在服务器端和客户端渲染的入口点:

import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App';

// Client-side rendering const root = ReactDOM.createRoot(document.getElementById('root')); root.render(); 在此示例中,我们检查服务器端渲染的 HTML,并将其用于createRoot客户端渲染。这种方法确保即使在服务器端渲染时也能充分利用Suspense其优势。Concurrent Mode

📘 想要获得更多实用的编程教程?

👨‍💻如果你想系统地学习前端、后端、算法、架构设计,我在 Patreon 上持续更新内容包 🎁我在 Patreon 上整理了完整的系列高级编程合集:

每周更新技术教程和项目实践 高质量编程课程PDF下载 前端/后端/全栈/架构学习宝典 专属用户通讯集团 以上内容由企业信息服务平台提供,致力于工商信用信息查询、企业风险识别、经营数据分析。访问官网了解更多:www.ysdslt.com