一、React-Router
2.React-Router的核心作用
- SPA导航:在单页面应用中管理不同视图的切换,无需重新加载页面
- URL与组件映射:将URL路径映射到对应的React组件,保持UI和URL同步
- 历史记录管理:支持浏览器历史记录的导航(前进/后退)
2.核心组件与API
1.路由器类型
BrowserRouter
- 使用
HTML5 History API(pushState,replaceState)
保持UI与URL同步
1import { BrowserRouter } from 'react-router-dom';
2<BrowserRouter>
3 <App />
4</BrowserRouter>
HashRouter
1<HashRouter>
2 <App />
3</HashRouter>
2.路由定义
Route:定义路径与组件的映射关系
- 使用URL的hash部分(如/#home),适用于不支持History API的旧浏览器
- v5版本:
1<Route path="/users" component={Users} />
1- v6版本
1<Route path="/users" element={<Users />} />
Routes(v6替代v5的Switch)
- 仅渲染第一个匹配的Route,提升性能
1<Routes>
2 <Route path="/" element={<Home />} />
3 <Route path="/about" element={<About />} />
4</Routes>
2.导航组件
- Link:生成无刷新导航链接
1<Link to="/about">关于</Link>
- Navigate(V6替代V5的Redirect):重定向到指定路径
1<Route path="/old" element={<Navigate to="/new" />} />
3.版本差异(v5 VS v6)
特性 | v5 | v6 |
---|---|---|
路由匹配 | 顺序匹配所有 Route | 优先精确匹配,使用 Routes |
嵌套路由 | 在子组件中定义嵌套 Route | 直接在父 Route 内嵌套 |
重定向 | Redirect 组件 | Navigate 组件 + replace 属性 |
编程式导航 | useHistory | useNavigate |
路由参数 | useParams 获取 | useParams + 动态路由语法优化 |
常见问题与解决方案
1.如何实现嵌套路由
- v5
1<Route path="/users" component={Users}>
2 <Route path="/users/:id" component={UserDetail} />
3</Route>
4
5{this.props.children}
- v6
1<Route path="/users" element={<Users />}>
2 <Route path=":id" element={<UserDetail />} />
3</Route>
4
5import { Outlet } from 'react-router-dom';
6function Users() {
7 return (
8 <div>
9 <h1>用户列表</h1>
10 <Outlet />
11 </div>
12 );
13}
2.如何动态处理路由参数?
1<Route path="/users/:userId" element={<UserProfile />} />
2
3
4import { useParams } from 'react-router-dom';
5function UserProfile() {
6 const { userId } = useParams();
7 return <div>用户ID: {userId}</div>;
8}
3.编程式导航的实现
- v5
1import { useHistory } from 'react-router-dom';
2function Login() {
3 const history = useHistory();
4 const handleLogin = () => {
5 history.push('/dashboard');
6 };
7 return <button onClick={handleLogin}>登录</button>;
8}
- v6
1import { useNavigate } from 'react-router-dom';
2function Login() {
3 const navigate = useNavigate();
4 const handleLogin = () => {
5 navigate('/dashboard', { state: { from: '/login' } });
6 };
7 return <button onClick={handleLogin}>登录</button>;
8}
4.路由守卫
1function PrivateRoute({ children }){
2 const isAuthenticated = useAuth();
3 return isAuthenticate ? chilren : <Navigate to="/login" />;
4
5}
6
7<Route
8 path="/dashbord"
9 element={
10 <PrivateRoute>
11 <Dashboard />
12 </PrivateRoute>
13 }
5.处理404页面
1<Routes>
2 <Route path="/" element={<Home />} />
3 <Route path="/about" element={<About />} />
4 <Route path="*" element={<NotFound />} />
5</Routes>
5.高级技巧与最佳实践
1.代码分割与懒加载
- 结合
React.lazy
和Suspense
实现按需加载
1const Users = React.lazy(() => import('./Users'));
2<Route path="/users" element={
3 <Suspense fallback={<Loading />}>
4 <Users />
5 </Suspense>
6} />
2.传递状态至路由组件
- 使用state属性传递
1navigate('/profile', { state: { userData: data } });
2
3const location = useLocation();
4const userData = location.state?.userData;
3.使用useRoutes配置式路由(V6)
- 集中管理路由配置
1const routes = useRoutes([
2 { path: '/', element: <Home /> },
3 { path: 'users', element: <Users />, children: [
4 { path: ':id', element: <UserDetail /> }
5 ]}
6]);
7return routes;
6.高频面试题
1.BrowserRouter和HashRouter有什么区别?
- BrowserRouter使用
HTML5 History API
,URL格式为example.com/path
- HashRouter使用
URL Hash(example/#/path)
,兼容旧浏览器但不够美观
2.React-Router V6有哪些重大改进
- 引入Routes代替Switch,提升匹配逻辑
- 嵌套路由配置更简洁,支持相对路径
- 移除Redirect,改用Navigate
- element属性直接传递JSX元素,支持更灵活的组件组合
3.如何实现路由鉴权
- 使用高阶组件或自定义路由组件包裹需要保护的路径,检查用户权限后决定渲染目标组件还是重定向到登录页
4.为什么需要exact属性(V5)
- 确保路径完全匹配。例如,path=“/” 没有exact时会匹配所有以/开头的URL。v6中默认精确匹配,无需此属性。
二、性能优化
1.优化核心思路
- 减少不必要的渲染:避免组件因无关状态/props变化而重新渲染
- 降低计算开销:缓存高成本计算和函数引用
- 优化DOM操作:减少实际DOM的无效变更
- 合理加载资源:按需加载关键代码与数据
2.关键优化策略与实现
1.组件渲染控制
- React.memo:缓存函数组件渲染结果
1const MemoComponent = React.memo(Component, (prevProps, nextProps) => {
2 return prevProps.id === nextProps.id;
3});
- PureComponent:类组件自动浅比较props/state
1class OptimizedComponent extends React.PureComponent {
2
3}
- shouldComponentUpdate:手动控制类组件更新
1shouldComponentUpdate(nextProps, nextState) {
2 return this.props.data.id !== nextProps.data.id;
3}
2.高效数据管理
- useMemo:缓存复杂计算结果
1const processedData = useMemo(() => transformData(rawData), [rawData]);
- useCallback:稳定函数引用
1const handleClick = useCallback(() => {
2 submitData(id);
3}, [id]);
- 状态结构优化:扁平化数据,避免深层嵌套
1const [data, setData] = useState({ user: { profile: { name: '' } } });
2
3
4const [userName, setUserName] = useState('');
3.列表渲染优化
- key属性优化:使用唯一稳定标识
1{items.map(item => (
2 <ListItem key={item.id} data={item} />
3))}
- 虚拟列表技术:使用react-window实现
1import { FixedSizeList as List } from 'react-window';
2
3<List height={600} itemSize={35} itemCount={1000}>
4 {({ index, style }) => <div style={style}>Row {index}</div>}
5</List>
4.资源加载优化
- 代码分割:动态加载非关键组件
1const LazyComponent = React.lazy(() => import('./HeavyComponent'));
2
3<Suspense fallback={<Spinner />}>
4 <LazyComponent />
5</Suspense>
- 图片懒加载:使用
Intersection Observer
1const LazyImage = ({ src }) => {
2 const imageRef = useRef();
3 useEffect(() => {
4 const observer = new IntersectionObserver((entries) => {
5 if (entries[0].isIntersecting){
6 imgRef.current.src = src;
7 observer.unobserve(imgRef.current);
8 }
9 });
10 observer.observe(imgRef.current);
11 return () => observer.disconnect();
12 }, []);
13 return <img ref={imgRef} alt="Lazy loaded" />;
14}
3.性能分析工具
1. React DevTools Profiler
- 记录组件渲染耗时
- 查看渲染原因
2. Chorme Perfomance面板
- 分析JavaScript执行耗时
- 识别长任务(Long Tasks)
3. Lighthouse审计
- 综合评估性性能指标(FCP,TTI,TBT)
- 获取优化建议
4.高级优化技术
1.并发模式优化(React18+)
- 自动批处理:合并多个状态更新
1const handleClick = () => {
2 setCount(c => c + 1);
3 setValue(v => v + 1);
4};
- useTransition:区分紧急/非紧急更新
1const [isPending, startTransition] = useTransition();
2
3const handleSearch = (query) => {
4 startTransition(() => {
5 setSearchQuery(query);
6 });
7};
2.服务端渲染优化
- 流式SSR:分块传输HTML
1export async function getServerSideProps() {
2 return {
3 props: { data: await fetchData() },
4 };
5}
- 静态生成:预渲染静态页面
1export async function getStaticProps() {
2 return { props: { }, recalidate: 60 };
3}
5.常见性能陷阱与方案
问题 | 解决方案 |
---|---|
不必要的 Context 更新 | 拆分多个 Context,使用 useMemo 缓存 Provider 值 |
过度使用 useMemo | 仅对高开销计算使用,避免对小计算进行不必要的缓存 |
内存泄漏 | 及时清理定时器、事件监听器、订阅等副作用 |
大状态对象更新 | 使用 Immer 实现不可变更新,避免深拷贝性能问题 |
6.性能优化黄金法则
- 优先解决关键瓶颈:使用Profiler定位主要性能
- 避免过早优化:在出现可测量的性能问题后再实施优化
- 保持组件简单:单一职责组件更易优化
- 渐进增强:优先优化首屏关键路径,再处理次要内容
三、高级特性
1.错误边界
1.定义与作用
- 错误边界是React中的一种特殊类组件,用于
捕获其子组件树中发生的JavaScript错误
,防止这些错误导致整个应用崩溃。通过错误边界,开发者可以优雅地处理错误,并展示降级UI以提升用户体验
2.实现方式
错误边界必须使用类组件实现,并定义以下两个生命周期方法之一(或两者):
static getDerivedStateFromError(error)
- 作用:捕获子组件抛出的错误,返回一个状态对象来更新组件状态
- 触发时机:渲染阶段(Render Phase)
- 返回值:必须返回一个对象用于更新state,以控制是否显示降级UI
2.componentDidCatch(error, errorInfo)
- 作用:记录错误信息(如发送至监控平台)
- 触发时机:提交阶段(Commit Phase)
- 参数:
- error:抛出的错误对象
- errorInfo:包含组件栈信息的对象(componentStack)
1class ErrorBoundary extends React.Component {
2 state = { hasError: false };
3 static getDerivedStateFromError(error) {
4 return { hasError: true };
5 }
6
7 componentDidCatch(error, errorInfo) {
8 logErrorToService(error, errorInfo);
9 }
10
11 render() {
12 if (this.state.hasError) {
13 return <h1>Oops! Something went wrong.</h1>;
14 }
15 return this.props.children;
16 }
17}
3.使用场景
1.包裹高风险组件
1<ErrorBoundary>
2 <UnstableComponent />
3</ErrorBoundary>
2.全局兜底错误处理
1<ErrorBoundary>
2 <App />
3</ErrorBoundary>
4.错误边界的限制
可捕获的错误类型 | 无法捕获的错误类型 |
---|---|
子组件渲染期间的错误 | 事件处理器中的错误(需手动 try/catch ) |
生命周期方法中的错误 | 异步代码(如 setTimeout 、fetch ) |
构造函数中的错误 | 服务端渲染(SSR)的错误 |
子组件错误边界未处理的错误 | 错误边界自身抛出的错误 |
5.最佳实践
1.避免滥用
- 仅在关键组件或模块使用,而非整个组件
2.组合使用
- 多层错误边界实现局部错误隔离
1<ErrorBoundary>
2 <Header />
3 <ErrorBoundary>
4 <MainContent />
5 </ErrorBoundary>
6 <Footer />
7</ErrorBoundary>
3.try/catch互补
- 错误边界处理渲染错误
- try/catch处理事件处理器、异步代码错误
1function MyComponent() {
2 const handleClick = () => {
3 try {
4
5 } catch (error) {
6 logError(error);
7 }
8 };
9 return <button onClick={handleClick}>Click</button>;
10}
6.高频面试题
1.函数式组件能否作为错误边界?
- 不能。错误边界必须通过类组件的生命周期方法实现,函数式组件需包裹在类组件的错误边界中
2.错误边界可以捕获哪些阶段的错误?
- 仅捕获渲染阶段(如render、constructor、生命周期方法)的错误,无法捕捉提交阶段(如DOM操作)或异步代码中的错误
3.如何测试错误边界?
- 测试中模拟子组件抛出错误
- 验证错误边界是否显示降级UI
- 检查错误是否正确上报
1test('ErrorBoundary shows fallback UI on error', () => {
2 const ErrorComponent = () => {
3 throw new Error('Test error');
4 };
5 const { getByText } = render(
6 <ErrorBoundary>
7 <ErrorComponent />
8 </ErrorBoundary>
9 );
10 expect(getByText('Oops! Something went wrong.')).toBeInTheDocument();
11});
4.错误边界如何处理自身错误?
- 错误边界自身的错误会冒泡到上一层的错误边界。若没有父级边界,则导致整个应用崩溃
2.高阶组件
1.定义
高阶组件(Higher-Order Component)是React中用于复用组件逻辑的一种高级技巧。它是一个函数,接受一个组件作为参数,并返回一个新的增强组件。HOC本身不是组件,而是一个组件工厂函数
2.HOC的核心作用
- 逻辑复用:抽离多个组件的公共逻辑(如数据获取,权限控制)
- 增强组件能力:为组件注入额外的props或扩展生命周期行为
- 代码解耦:将业务逻辑与UI组件分离,提升可维护性
3.HOC的实现
1.属性代理(Props Proxy)
- 特点:HOC包裹目标组件,通过props传递数据或方法
1function withLogging(wrappedComponent) {
2 return class extends React.Component {
3 componentDidMount() {
4 console.log('Component is mounted:', WrappedComponent.name);
5 }
6 render() {
7
8 return <WrappedComponent {...this.props} />;
9 }
10 }
11}
12
13const EnhancedComponent = withLogging(MyComponent);
2.反向继承(Inheritance Inversion)
- 特点:通过继承目标组件,控制其渲染流程(较少使用)
1function withEnhancement(WrappedComponent) {
2 return class extends WrappedComponent {
3 render() {
4
5 const elements = supoer.render();
6 return React.cloneElement(elements, { newPorps: 'value' });
7 }
8 }
9}
10
11const EnhancedComponent = withEnhancement(MyComponent);
4.HOC应用场景
场景 | 示例 HOC | 功能 |
---|---|---|
权限控制 | withAuth | 检查用户权限,未登录则跳转 |
数据请求 | withFetchData | 统一处理 API 请求与状态管理 |
UI 功能增强 | withHover /withClickOutside | 添加悬停或点击外部关闭功能 |
状态管理 | Redux connect | 连接组件与 Redux Store |
5.注意事项
1.不要修改原始组件
- 使用组合而非继承,避免直接修改原始组件的原型
2.透传无关props
- 确保HOC传递所有与自身无关的props到被包裹组件
1render() {
2 const { extraProp, ...restProps } = this.props;
3 return <WrappedComponent {...restProps} />;
4}
3.处理静态方法
- 使用
hoist-non-react-statics
复制静态方法到新组件
1npm install hoist-non-react-statics
1import hoistNonReactStatic from 'hoist-non-react-statics';
2
3function withEnhancement(WrappedComponent) {
4 class EnhancedComponent extends React.Component { }
5 hoistNonReactStatic(EnhancedComponent, WrappedComponent);
6 return EnhancedComponent;
7}
4.Ref传递问题
- 使用
React.forwardRef
转发Ref到被包裹组件
1function withRefForwarding(WrappedComponent) {
2 class EnhancedComponent extends React.Componnet {
3 render() {
4 const { forwardedRef, ...resetProps } = this.props;
5 return <WrappedComponent ref={forwardedRef} {...resetProps} />;
6 }
7 }
8 return React.forwardRef((props, ref) => (
9 <EnhancedComponent forwardedRef={ref} {...props} />;
10 ))
11}
6.HOC和Hooks对比
维度 | HOC | Hooks |
---|---|---|
适用组件类型 | 类组件/函数组件 | 仅函数组件 |
逻辑复用方式 | 包裹组件,形成组件树层级 | 在组件内部直接调用 Hook 函数 |
代码组织 | 可能引入多层嵌套,可读性下降 | 扁平化逻辑,易于追踪数据流 |
性能影响 | 可能因层级嵌套导致不必要的渲染 | 依赖数组精准控制更新 |
学习曲线 | 需理解高阶函数和组件组合 | 需掌握闭包和依赖数组规则 |
7.高频面试题
1.HOC的优缺点
-
优点:
- 跨组件复用逻辑,减少代码冗余
- 适用于类组件,兼顾旧项目
-
缺点:
- 组件层级嵌套过深,调试困难
- 需处理静态方法和Ref传递
- 可能引发props命名冲突
2.如何避免HOC的props命名冲突?
- 使用命名空间或特点前缀
1<WrappedComponent hocData={data} {...restProps} />
- 在HOC中过滤专属props
1render() {
2 const { hocProp, ...passThroughProps } = this.props;
3 return <WrappedComponent {...passThroughProps} />;
4}
3.HOC在React生态的典型应用有哪些?
- Redux:
connect(mapStateToProps, mapDispatchToProps)(Component)
- React Router:
withRouter(Component)
- Material-UI:
whithStyle(styles)(Component)
4.HOC是否会导致性能问题?如何优化?
- 问题:每次父组件渲染时创建新的HOC实例,导致子组件重新挂载
- 优化:在组件外部定义HOC,而非在render方法中动态创建
1function Parent() {
2 const HocComponent = withLogging(Child);
3 return <HocComponent />;
4}
5
6
7const EnhancedChild = withLogging(Child);
8function Parent() {
9 return <EnhancedChild />;
10}
3.服务端渲染方案
1.核心优势
- SEO友好:爬虫直接解析服务端返回的HTML,提升搜索引擎排名
- 首屏性能优化:减少客户端渲染的白屏时间,提升用户体验
- 兼容性保障:确保低端设备或禁用JavaScript的环境下基础内容可访问
2.主流SSR方案对比
方案 | 特点 | 适用场景 |
---|---|---|
Next.js | 开箱即用、约定式路由、支持 SSG/SSR/ISR | 全栈应用、SEO 要求高的项目 |
Gatsby | 基于 GraphQL 的静态站点生成(SSG)、插件生态丰富 | 内容型网站(博客、文档) |
自定义 SSR | 灵活控制渲染流程、深度定制化 | 复杂企业级应用、特殊架构需求 |
React Server Components | 混合渲染(服务端/客户端组件结合)、减少客户端 JS 体积 | 动态内容与静态内容混合的场景 |
3.Next.js实现SSR深度解析
1.页面级SSR
使用getServerSideProps
在每次请求时生成页面
1export async function getServerSideProps(context) {
2 const data = await fetchData(context.data.id);
3 return { props: { data } };
4}
5
6function Page({ data }) {
7 return <div>{data}</div>;
8}
2.增量静态再生(ISR)
结合静态生成与按需更新
1export async function getStaticProps() {
2 const data = await fetchData();
3 return {
4 props: { data },
5 revalidate: 60
6 };
7}
3.客户端水合(Hydration)
自动处理服务端与客户端渲染链接
1import { renderToString } from 'react-dom/server';
2const html = renderToString(<App />);
3
4
5import { hydrateRoot } from 'react-dom/client';
6hydrateRoot(document.getElementById('root'), <App />);
4.自定义SSR实现步骤
1.项目结构配置
1- src/
2 - client/
3 - index.js
4 - server/
5 - index.js
2.Webpack多环境配置
1module.export = {
2 entry: './src/client/index.js',
3 output: {
4 filename: 'client-bundle.js',
5 path: path.resolve(__dirname, 'dist'),
6 }
7};
8
9module.exports = {
10 entry: './src/server/index.js',
11 target: 'node',
12 output: {
13 filename: 'server-boudle.js',
14 path: path.resolve(__dirname, 'dist'),
15 }
16};
3.服务端渲染核心逻辑
1import express from 'express';
2import React from 'react';
3import { renderToString } from 'react-dom/server';
4import App from '../shared/App';
5
6const app = express();
7app.get('*', (req, res) => {
8 const html = renderToString(<App />);
9 res.send(`
10 <!DOCTYPE html>
11 <html>
12 <head>
13 <title>SSR App</title>
14 </head>
15 <body>
16 <div id="root">${html}</div>
17 <script src="/client-bundle.js"></script>
18 </body>
19 </html>
20 `);
21});
4.数据预取和状态同步
1const fetchData = async () => {
2 const res = await fetch('https://api.example.com/data');
3 return res.json();
4};
5
6
7window.__INITIAL_STATE__ = serverData;
8
9
10const initialState = window.__INITIAL_STATE__;
11const store = configureStore(initialState);
12hydrateRoot(document.getElementById('root'), <App store={store} />);
5.性能优化策略
1.缓存机制
1const microCache = new LRU({
2 max: 100,
3 maxAge: 1000 * 60
4});
5
6app.get('*', (req, res) => {
7 const cachedHtml = microCache.get(req.url);
8 if (cachedHtml) return res.send(cachedHtml);
9
10 const html = renderToString(<App />);
11 microCache.set(req.url, html);
12 res.send(html);
13});
2.流式渲染
1import { renderToPipeableStream } from 'react-dom/server';
2
3app.use((req, res) => {
4 const stream = renderToPipeableStream(<App />, {
5 onShellReady() {
6 res.setHeader('Content-type', 'text/html');
7 stream.pipe(res);
8 }
9 });
10});
3.代码分割
1import loadable from '@loadable/component';
2const LazyComponent = loadable(() => import('./HeavyComponent'));
3
4
5import { ChunkExtractor } from '@loadable/server';
6const extractor = new ChunkExtractor({ statsFile: 'dist/loadable-stats.json' });
7const jsx = extractor.collectChunks(<App />);
8const html = renderToString(jsx);
9const scriptTags = extractor.getScriptTags();
6.常见问题与解决方案
问题 | 解决方案 |
---|---|
客户端-服务端状态不一致 | 使用 Redux 或 Context API 同步初始化状态 |
window 未定义错误 | 通过条件判断限制客户端专用代码执行:if (typeof window !== 'undefined') |
样式闪烁(FOUC) | 使用 isomorphic-style-loader 提取服务端样式到 <style> 标签 |
内存泄漏 | 监控服务器内存使用,使用 --max-old-space-size 调整 Node.js 内存限制 |
4.React18+新特性
1.并发渲染
React 18的核心更新是引入并发渲染能力,允许React在渲染过程中中断并优先处理更高优先级的任务(比如用户输入),从而提升响应速度。
关键机制
- 时间切片:将渲染任务拆分成小块,避免长时间阻塞主线程
- 优先级调度:用户交互(如点击)优先于数据更新(如API响应)
相关API
startTransition
:标记非紧急更新,可被高优先级任务打断
1import { startTransition } from 'react';
2
3const handleSearch = (query) => {
4 startTransition(() => {
5 setSearchQuery(query);
6 });
7};
useTransition
:跟踪过渡状态,显示加载指示
1const [isPending, startTransition] = useTransition();
2
3return (
4 <button onClick={() => startTransition(handleClick)}>
5 {isPending ? '加载中...' : '提交'}
6 </button>
7);
2.自动批处理
React 18默认将多次状态更新合并为单次渲染,减少不必要的重复渲染
更新场景对比
场景 | React 17 及之前 | React 18 |
---|---|---|
事件处理器中的更新 | 批量处理 | 批量处理 |
setTimeout/Promise 中的更新 | 不批量处理 | 批量处理 |
强制同步更新
1import { flushSync } from 'react-dom';
2
3flushSync(() => {
4 setCount(c => c + 1);
5});
3.流式服务端渲染
通过分块传输HTML和选择性水合,显著提升服务端渲染性能
核心改进
- 流式传输:服务器逐步发送HTML到客户端,缩短首屏时间
- 并行水合:客户端在接收HTML时逐步激活交互功能,无需等待全部内容加载
1import { renderToPipeableStream } from 'react-dom/server';
2
3app.get('/', (req, res) => {
4 const stream = renderToPipeableStream(<App />, {
5 onShellReady() {
6 res.setHeader('Content-type', 'text/html');
7 stream.pipe(res);
8 },
9 bootstrapScripts: ['/main.js']
10 });
11});
4.新根API与严格模式增强
1.新根API createRoot
替换原有的ReactDOM.render
,启用并发功能
1ReactDOM.render(<App />, document.getElementById('root'));
2
3
4const root = ReactDOM.createRoot(document.getElementById('root'));
5root.render(<App />);
2.严格模式
- 模拟卸载-挂载:开发环境下组件挂载后立即卸载再重新挂载,检测副作用清理问题
- 重复渲染检测:故意双调用组件函数和Hook,暴露潜在副作用
5.新Hook与API
1.useId
- 生成唯一ID,解决服务端与客户端ID不一致的问题
1const id = useId();
2return <label htmlFor={id}>用户名</label>;
2.useDeferredValue
- 延迟更新非关键UI,保持高优先级交互流程
1const deferredQuery = useDeferredValue(query);
2return <SearchResults query={deferredQuery} />;
3.useSyncExternalStore
- 简化外部状态库(如Redux)集成,避免并发渲染下的撕裂问题
1const state = useSyncExternalStore(store.subscribe, store.getState);
6.改进的Suspense功能
- 支持在SSR中与流式渲染结合,优化体验
1<Suspense fallback={<Spinner />}>
2 <Comments /> {}
3</Suspense>
个人笔记记录 2021 ~ 2025