news 2026/5/19 2:54:06

React Concurrent Mode:构建响应式用户界面

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
React Concurrent Mode:构建响应式用户界面

React Concurrent Mode:构建响应式用户界面

前言

各位前端小伙伴,不知道你们有没有遇到过这种情况:当页面进行大量渲染时,整个界面会卡住,用户无法进行任何操作!

我曾经开发过一个数据密集型应用,当加载大量数据时,页面会卡顿几秒。后来我引入了React Concurrent Mode,用户体验大大提升!

什么是Concurrent Mode?

Concurrent Mode是React 18引入的新特性,它允许React在渲染过程中中断工作,优先响应用户输入,从而提供更流畅的用户体验。

Concurrent Mode工作原理

┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 用户输入 │ │ React渲染 │ │ 浏览器绘制 │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ │ 1. 用户输入事件 │ │ │───────────────────────>│ │ │ │ │ │ │ 2. 中断渲染 │ │<───────────────────────│ │ │ │ │ │ 3. 处理用户输入 │ │ │───────────────────────>│ │ │ │ │ │ │ 4. 恢复渲染 │ │<───────────────────────│ │ │ │ │ │ │ │ 5. 绘制结果 │ │ │────────────────────────>│

启用Concurrent Mode

在React 18中启用

// main.js import { createRoot } from 'react-dom/client' import App from './App' const root = createRoot(document.getElementById('root')) root.render(<App />)

与Legacy Mode对比

// Legacy Mode (React 17及之前) import ReactDOM from 'react-dom' ReactDOM.render(<App />, document.getElementById('root')) // Concurrent Mode (React 18+) import { createRoot } from 'react-dom/client' const root = createRoot(document.getElementById('root')) root.render(<App />)

Concurrent Mode核心特性

1. 可中断渲染

function ExpensiveComponent({ items }) { return ( <div> {items.map((item) => ( <ExpensiveItem key={item.id} item={item} /> ))} </div> ) } // 在Concurrent Mode下,这个组件的渲染可以被中断 // 当用户输入时,React会暂停渲染,处理输入后再继续

2. 优先级调度

import { startTransition } from 'react' function SearchInput({ onSearch }) { const [query, setQuery] = useState('') function handleChange(e) { const value = e.target.value setQuery(value) startTransition(() => { onSearch(value) }) } return <input value={query} onChange={handleChange} /> }

3. Suspense改进

import { Suspense } from 'react' function Profile() { return ( <Suspense fallback={<Loading />}> <UserProfile /> </Suspense> ) } // 在Concurrent Mode下,Suspense可以嵌套使用 function Dashboard() { return ( <div> <Suspense fallback={<HeaderLoading />}> <Header /> </Suspense> <Suspense fallback={<ContentLoading />}> <Content /> </Suspense> </div> ) }

startTransition

基本用法

import { startTransition, useState } from 'react' function App() { const [count, setCount] = useState(0) const [list, setList] = useState([]) function handleClick() { setCount(c => c + 1) startTransition(() => { const newList = generateHugeList() setList(newList) }) } return ( <div> <button onClick={handleClick}>Increment</button> <div>{count}</div> <List items={list} /> </div> ) }

useTransition Hook

import { useTransition, useState } from 'react' function SearchResults({ query }) { const [isPending, startTransition] = useTransition() const [results, setResults] = useState([]) useEffect(() => { startTransition(() => { const newResults = search(query) setResults(newResults) }) }, [query, startTransition]) return ( <div> {isPending && <Spinner />} <ResultsList results={results} /> </div> ) }

useDeferredValue

基本用法

import { useDeferredValue, useState } from 'react' function SearchResults({ query }) { const deferredQuery = useDeferredValue(query) const results = useMemo(() => { return search(deferredQuery) }, [deferredQuery]) return <ResultsList results={results} /> }

结合Suspense

import { useDeferredValue, Suspense } from 'react' function SearchResults({ query }) { const deferredQuery = useDeferredValue(query) return ( <Suspense fallback={<Loading />}> <Results query={deferredQuery} /> </Suspense> ) }

Concurrent Mode实战

实现流畅的搜索体验

import { useState, startTransition, useTransition } from 'react' function SearchApp() { const [query, setQuery] = useState('') const [results, setResults] = useState([]) const [isPending, startTransition] = useTransition() function handleSearch(value) { setQuery(value) startTransition(() => { const newResults = performSearch(value) setResults(newResults) }) } return ( <div> <input type="text" value={query} onChange={(e) => handleSearch(e.target.value)} placeholder="Search..." /> {isPending && <div>Loading...</div>} <ul> {results.map((result) => ( <li key={result.id}>{result.title}</li> ))} </ul> </div> ) }

实现懒加载列表

import { useState, startTransition, useRef, useCallback } from 'react' function VirtualList({ items }) { const [visibleItems, setVisibleItems] = useState([]) const containerRef = useRef(null) const loadMore = useCallback((startIndex, count) => { startTransition(() => { const newItems = items.slice(startIndex, startIndex + count) setVisibleItems(prev => [...prev, ...newItems]) }) }, [items]) useEffect(() => { loadMore(0, 20) }, [loadMore]) return ( <div ref={containerRef} onScroll={handleScroll}> {visibleItems.map((item) => ( <Item key={item.id} item={item} /> ))} </div> ) }

Concurrent Mode最佳实践

1. 使用startTransition包装非紧急更新

function handleClick() { // 紧急更新:立即更新UI setCount(c => c + 1) // 非紧急更新:可以延迟执行 startTransition(() => { setItems(generateItems()) }) }

2. 使用useDeferredValue延迟非关键渲染

function FilteredList({ items, filter }) { const deferredFilter = useDeferredValue(filter) const filteredItems = useMemo(() => { return items.filter(item => item.includes(deferredFilter)) }, [items, deferredFilter]) return <List items={filteredItems} /> }

3. 使用Suspense处理异步加载

function App() { return ( <Suspense fallback={<GlobalLoading />}> <Header /> <main> <Suspense fallback={<ContentLoading />}> <Content /> </Suspense> </main> </Suspense> ) }

常见问题

问题1:渲染结果不一致

解决方案

  • 确保state更新是纯函数
  • 使用useMemo缓存计算结果
  • 检查是否有副作用影响渲染

问题2:性能没有提升

解决方案

  • 使用startTransition包装耗时操作
  • 检查是否有不必要的重新渲染
  • 使用React DevTools Profiler分析

问题3:Suspense fallback闪烁

解决方案

  • 添加minDuration属性
  • 使用稳定的key值
  • 考虑使用渐进式加载

Concurrent Mode vs Legacy Mode

特性Legacy ModeConcurrent Mode
渲染方式同步阻塞异步可中断
用户体验可能卡顿流畅响应
优先级单一优先级多优先级调度
Suspense基础支持完整支持
兼容性React 18+

总结

Concurrent Mode是React 18最重要的更新之一。通过使用Concurrent Mode,我们可以:

  1. 提升响应性:优先响应用户输入
  2. 避免卡顿:可中断渲染
  3. 优化体验:使用优先级调度
  4. 简化异步:改进的Suspense

现在,开始使用Concurrent Mode构建更流畅的应用吧!你的用户会感谢你的!

最后一句忠告:不要过度使用startTransition,只包装真正耗时的操作!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/19 2:51:12

Hermes 的核心架构 Harness:上下文、工具、权限与执行控制

上一篇写 Hermes-Agent&#xff0c;我们选了一条比较笨但好用的路&#xff1a;跟一条消息走一遍。 从终端里敲下一句话&#xff0c;到 Agent 把最后一个字回到屏幕上&#xff0c;中间其实绕了很长一圈&#xff1a; 消息先被入口收进去&#xff0c;变成内部统一的消息&#xf…

作者头像 李华
网站建设 2026/5/19 2:48:15

FPGA硬件随机数生成技术与零阶优化加速

1. FPGA硬件随机数生成技术概述随机数生成(RNG)在现代计算系统中扮演着关键角色&#xff0c;特别是在密码学、蒙特卡洛模拟和机器学习等领域。FPGA因其并行计算能力和可重构特性&#xff0c;成为实现高效RNG的理想平台。传统软件RNG面临两个主要瓶颈&#xff1a;生成速度受限于…

作者头像 李华
网站建设 2026/5/19 2:48:07

ChatGPT免费版 vs Plus版:12项关键指标横向测评(含真实延迟测试、JSON输出成功率、长文档摘要准确率),第9项结果震惊团队

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;ChatGPT免费版与Plus版的核心定位差异 ChatGPT免费版与Plus版并非简单的“功能增减”关系&#xff0c;而是基于不同用户场景与产品目标构建的差异化服务模型。免费版面向广泛公众&#xff0c;强调可访问性、教…

作者头像 李华