react性能优化

117 阅读4分钟

React 性能优化(全面版)

React 性能优化通常可以分为 渲染优化、状态管理优化、组件设计优化、打包优化、网络优化、列表优化、内存优化 七大类。


一、减少不必要的渲染(最重要)

1. React.memo

用于函数组件缓存。

const Child = React.memo((props) => {
  console.log('Child Render');
  return <div>{props.name}</div>;
});

未使用

<Child name="Tom" />

父组件更新:

setCount(count + 1)

Child也会重新渲染。

使用后

props没变:

React.memo(Child)

不会重新渲染。


2. useMemo

缓存计算结果。

错误

const list = bigData.filter(item => item.age > 20);

每次render都会执行。

优化

const list = useMemo(() => {
  return bigData.filter(item => item.age > 20);
}, [bigData]);

适用:

  • 大数据计算
  • 表格数据处理
  • 树结构转换
  • 图表数据处理

3. useCallback

缓存函数。

问题

<Child onClick={() => handleClick()} />

每次都会生成新函数。

导致:

React.memo

失效。

优化

const handleClick = useCallback(() => {
  console.log('click');
}, []);

<Child onClick={handleClick} />

4. useRef代替State

错误

const [timer,setTimer] = useState(null);

修改会触发渲染。

优化

const timerRef = useRef(null);

timerRef.current = setTimeout(...)

不会触发render。

适合:

  • 定时器
  • DOM
  • websocket实例
  • 缓存变量

二、列表性能优化

大项目最容易卡顿的地方。


5. key不要乱写

错误

{
  list.map((item,index)=>(
      <Item key={index}/>
  ))
}

删除数据后:

[1,2,3,4]

变:

[2,3,4]

React会重新比较大量节点。

正确

<Item key={item.id}/>

6. 虚拟列表

10000条数据:

list.map(...)

直接卡死。

使用:

  • react-window
  • react-virtualized
<FixedSizeList
  height={600}
  itemCount={10000}
  itemSize={50}
>

只渲染可视区域。


7. 分页加载

不推荐

一次加载10000条

推荐

每页20条

或者:

无限滚动

三、状态管理优化


8. 状态不要放太高

错误

App
 ├─A
 ├─B
 ├─C

所有状态放:

App

更新一次:

App重新render

所有子组件更新。


优化

状态下沉

A自己维护state

只更新A。


9. Context拆分

错误

<UserContext.Provider
 value={{
   user,
   theme,
   language
 }}
>

修改theme:

user组件也更新

优化

UserContext
ThemeContext
LanguageContext

拆分Context。


10. Zustand替代复杂Context

大型项目推荐:

Zustand 官方网站

const count = useStore(state => state.count)

按需订阅。

避免全局刷新。


四、组件设计优化


11. 组件拆分

错误

Page.jsx

2000行代码

任何状态变化:

整个页面render

优化

Page
 ├ Header
 ├ Search
 ├ TableFooter

细粒度更新。


12. 懒加载组件

const ReportPage = React.lazy(() =>
 import('./ReportPage')
);
<Suspense fallback={<Loading/>}>
   <ReportPage />
</Suspense>

13. 路由懒加载

const Home = lazy(() => import('./Home'));

减少首屏体积。


14. 条件渲染优化

错误

{
  show && <BigTable />
}

频繁卸载挂载。


优化

<div style={{
 display: show ? 'block' : 'none'
}}>
   <BigTable />
</div>

适用于频繁切换场景。


五、表格性能优化(企业项目重点)

你做过性能平台项目,这部分面试经常问。


15. 表格列配置缓存

错误

const columns = [ ...]

每次render重新创建。


优化

const columns = useMemo(() => [ ...], []);

16. render函数缓存

错误

{
 render: () => (
   <Button>编辑</Button>
 )
}

优化

const renderAction = useCallback(
  (record)=>{},
  []
);

17. 大表格虚拟滚动

Ant Design:

<Table
 scroll={{
   y:600
 }}
 virtual
/>

18. Echarts销毁优化

页面切换:

chart.dispose();

避免内存泄漏。


六、请求性能优化


19. 防抖(debounce)

搜索框:

lodash.debounce
const search = debounce(() => {
  api();
},500);

20. 节流(throttle)

滚动事件:

lodash.throttle
const scroll = throttle(()=>{
},300);

21. 请求缓存

react-query

现在叫:

TanStack Query 官方网站

useQuery(...)

自动缓存。


22. 请求合并

错误

getUser()
getRole()
getDept()

优化

Promise.all([
 getUser(),
 getRole(),
 getDept()
])

七、打包优化


23. Tree Shaking

错误

import _ from 'lodash';

优化

import debounce from 'lodash/debounce';

24. Code Splitting

import()

动态加载。


25. Gzip/Brotli压缩

服务器开启:

gzip on;
brotli on;

26. CDN资源

react.min.js

走CDN。


27. 图片优化

使用

  • WebP
  • AVIF

懒加载

<img
 loading="lazy"
/>

八、React18优化


28. useTransition

降低优先级更新。

const [isPending,startTransition]
 = useTransition();

startTransition(()=>{
 setList(data);
});

适合:

  • 搜索
  • 大列表

29. useDeferredValue

const deferredKeyword =
 useDeferredValue(keyword);

输入不卡顿。


九、内存泄漏优化


30. 清理事件

useEffect(()=>{
  window.addEventListener(...);

  return ()=>{
    window.removeEventListener(...);
  };
},[]);

31. 清理定时器

useEffect(()=>{
 const timer = setInterval(...);

 return ()=>{
   clearInterval(timer);
 };
},[]);

32. 取消请求

const controller =
 new AbortController();

fetch(url,{
 signal:controller.signal
});

return ()=>{
 controller.abort();
}

十、React项目面试必答性能优化方案

如果面试官问:

React项目做过哪些性能优化?

可以按这个顺序回答:

  1. React.memo减少子组件渲染
  2. useMemo缓存复杂计算
  3. useCallback缓存函数
  4. 状态下沉,避免全局刷新
  5. Context拆分或使用Zustand
  6. 表格列配置useMemo缓存
  7. 大数据列表使用虚拟滚动
  8. 搜索使用防抖
  9. 路由和组件懒加载
  10. Tree Shaking + Code Splitting
  11. React18 useTransition优化大列表
  12. 清理事件、定时器、防止内存泄漏

对于你目前做过的 云鉴性能平台(React + Ant Design + ECharts) ,最有价值、最容易写进简历的优化点是:

  • 表格虚拟滚动(千级数据)
  • columns/useMemo缓存
  • 搜索条件防抖
  • ECharts按需渲染与dispose销毁
  • React.memo组件级缓存
  • 路由懒加载
  • Promise.all接口并发
  • Zustand/Redux选择性订阅
  • React Query缓存接口数据
  • React18 useTransition优化搜索结果渲染