跳转到主要内容

性能

性能优化应该由测量驱动:先定位,再修复,最后验证收益,避免“为优化而优化”。

很多团队浪费时间,是因为优化了“容易改的地方”,而不是“真正慢的地方”。测量能让你保持诚实。

性能通常来自哪里

大多数问题都能归到下面三类。先分类,再选杠杆,优化会更稳定。

  • 渲染太多:状态/Context 变更触发大范围重渲染。
  • 渲染太频繁:高频更新没有节流/合并。
  • 渲染太慢:昂贵计算或大列表。

Profiling 工作流

  1. 选择可测场景(滚动/输入/导航)并稳定复现。
  2. 记录基线:慢在哪里、慢多少、时间花在哪。
  3. 一次只修一个热点,再复测验证收益。
TypeScript
import { Profiler } from 'react';

export function ProfiledArea({ children }: { children: React.ReactNode }) {
  return (
    <Profiler
      id="Main"
      onRender={(
        id,
        phase,
        actualDuration
      ) => {
        console.log(id, phase, actualDuration);
      }}
    >
      {children}
    </Profiler>
  );
}

什么时候该用 memo

当组件渲染昂贵且大多数时候 `props` 稳定时,`memo` 才更可能带来净收益。

  • `memo` 有成本:比较、闭包保留与心智负担。只在“值得”的地方用。
  • 稳定的 props 比 memo 更关键:避免无意义地重建对象/函数。
  • 拆分状态:把高频更新限制在局部,避免牵连大子树。
TypeScript
import { memo, useMemo } from 'react';

const Row = memo(function Row({ value }: { value: number }) {
  return <div>{value}</div>;
});

export function List({ items }: { items: number[] }) {
  const even = useMemo(() => items.filter((x) => x % 2 === 0), [items]);
  return (
    <div>
      {even.map((x) => (
        <Row key={x} value={x} />
      ))}
    </div>
  );
}

大列表

  • 当列表很大且视口只显示一小段时,使用虚拟化。
  • 数据天然分块时,分页/无限滚动往往比一次渲染更合适。

高频更新与体感性能

如果输入/拖拽发卡,问题往往不是“渲染太多”,而是“渲染阻塞了输入响应”。用调度工具把紧急更新保持流畅。

换句话说:把“紧急更新”(输入回显)保持即时,把“非紧急更新”(过滤大列表)延后执行。

  • `useTransition`:把非紧急更新标记为可延后,让输入保持即时响应。
  • `useDeferredValue`:延迟使用高频值派生出来的 UI 渲染。
TypeScript
import { useState, useTransition } from 'react';

export function SearchBox() {
  const [query, setQuery] = useState('');
  const [isPending, startTransition] = useTransition();
  const [committed, setCommitted] = useState('');

  return (
    <div>
      <input
        value={query}
        onChange={(e) => {
          const next = e.target.value;
          setQuery(next);
          startTransition(() => setCommitted(next));
        }}
        placeholder="Search…"
      />
      <div>{isPending ? 'Loading…' : null}</div>
      <Results query={committed} />
    </div>
  );
}

function Results({ query }: { query: string }) {
  return <div>Query: {query}</div>;
}

上线检查清单

  • 性能优化有测量证据:有 before/after 对比。
  • 热点从源头修复(拆 state、建立 memo 边界),而不是全站乱加 memo。
  • 大列表已分块/虚拟化;`pending` 期间交互保持响应。
  • 导航具备 `loading`/`error`,避免瀑布请求。

延伸阅读

性能 - Guides - React 文档 - React 文档