React对于流式数据和非流式数据的处理和优化
React 在处理流式数据和非流式数据时,可以借助其组件模型、状态管理以及 React 18 引入的并发特性来实现高效的数据处理与渲染优化。
文章目录
- 一、流式数据(Streaming Data)
- 1. 定义
- 2. 常见来源
- 3. 处理方式
- 使用 `useState` / `useReducer` 管理状态
- 使用 `useRef` 存储引用(避免重复渲染)
- 自定义 Hook 封装逻辑
- 使用 Web Worker 处理复杂计算
- 渲染优化建议
- 二、非流式数据(Non-streaming Data)
- 1. 定义
- 2. 常见来源
- 3. 处理方式
- 使用 `useEffect` 触发一次性请求
- 使用 SWR / React Query 进行数据缓存与异步管理
- SWR 示例:
- React Query 示例:
- Suspense + Promise 支持异步依赖
- 预加载 & 缓存策略
- 三、通用优化策略
- 总结对比
一、流式数据(Streaming Data)
1. 定义
流式数据是指持续不断产生并实时传输的数据,例如通过 WebSocket、Server-Sent Events (SSE) 等方式获取的数据。
2. 常见来源
- WebSocket 实时通信
- Server-Sent Events (SSE)
- MQTT(物联网)
- 长轮询(Long Polling)
3. 处理方式
使用 useState
/ useReducer
管理状态
const [messages, setMessages] = useState<string[]>([]);useEffect(() => {const ws = new WebSocket('wss://example.com/socket');ws.onmessage = (event) => {setMessages(prev => [...prev, event.data]);};return () => ws.close();
}, []);
使用 useRef
存储引用(避免重复渲染)
适用于保存连接对象或缓存数据:
const socketRef = useRef<WebSocket | null>(null);
自定义 Hook 封装逻辑
function useWebSocket(url: string) {const [messages, setMessages] = useState<string[]>([]);useEffect(() => {const ws = new WebSocket(url);ws.onmessage = (event) => setMessages(prev => [...prev, event.data]);return () => ws.close();}, [url]);return messages;
}
使用 Web Worker 处理复杂计算
避免主线程阻塞,适合在后台处理大量流式数据。
渲染优化建议
- 虚拟滚动(Virtual Scrolling):使用
react-window
或react-virtualized
只渲染可视区域内容。 - 节流/防抖(Throttle/Debounce):控制高频更新频率。
- React.memo / useMemo / useCallback:减少不必要的子组件重新渲染。
二、非流式数据(Non-streaming Data)
1. 定义
非流式数据是一次性加载完成的数据,通常来自 HTTP 请求、本地存储等,有明确的开始和结束。
2. 常见来源
- RESTful API
- GraphQL 查询
- localStorage / IndexedDB
- 表单提交、静态资源加载
3. 处理方式
使用 useEffect
触发一次性请求
const [data, setData] = useState(null);useEffect(() => {fetch('/api/data').then(res => res.json()).then(setData);
}, []);
使用 SWR / React Query 进行数据缓存与异步管理
推荐使用第三方库进行更高级的数据管理:
SWR 示例:
import useSWR from 'swr';const fetcher = (url: string) => fetch(url).then(res => res.json());function MyComponent() {const { data, error } = useSWR('/api/data', fetcher);if (error) return <div>Failed to load</div>;if (!data) return <div>Loading...</div>;return <div>{JSON.stringify(data)}</div>;
}
React Query 示例:
import { useQuery } from 'react-query';function useGetData() {return useQuery(['data'], () =>fetch('/api/data').then(res => res.json()));
}
Suspense + Promise 支持异步依赖
React 18 支持使用 Suspense
来包裹异步加载组件:
const AsyncDataComponent = React.lazy(() => import('./DataComponent'));function App() {return (<React.Suspense fallback="Loading..."><AsyncDataComponent /></React.Suspense>);
}
预加载 & 缓存策略
- 使用
<link rel="prefetch">
提前加载资源。 - 利用 Service Worker 或 LocalStorage 缓存接口响应。
三、通用优化策略
优化点 | 描述 |
---|---|
React.memo | 避免子组件不必要重渲染 |
useMemo | 缓存计算结果,避免重复执行 |
useCallback | 缓存函数引用,防止子组件频繁更新 |
代码分割 | 使用 React.lazy 和 Suspense 按需加载组件 |
服务端渲染(SSR) | 提升首屏性能,适用于非流式数据 |
骨架屏 / 占位符 | 提升用户体验,避免白屏 |
总结对比
类型 | 数据特点 | 获取方式 | 处理方式 | 优化重点 |
---|---|---|---|---|
流式数据 | 实时、连续、无边界 | WebSocket、SSE | 持续监听、逐步更新 | 防止频繁渲染、内存泄漏 |
非流式数据 | 静态、一次性、有界 | HTTP、LocalStorage | 一次性加载、缓存 | 加载速度、缓存策略 |