专栏名称: 奇舞精选
《奇舞精选》是由奇舞团维护的前端技术公众号。除周五外,每天向大家推荐一篇前端相关技术文章,每周五向大家推送汇总周刊内容。
目录
相关文章推荐
爱平度  ·  ​2月5日,拍到了! ·  18 小时前  
伯虎财经  ·  DeepSeek,做AI竞争的破局者 ·  昨天  
科技美学官方  ·  小米双Ultra来了 ·  2 天前  
51好读  ›  专栏  ›  奇舞精选

React Compiler 进阶: useRef 也可以被淘汰啦

奇舞精选  · 公众号  · 科技自媒体  · 2024-09-05 18:00

主要观点总结

本文介绍了React Compiler的重要性和优势,详细阐述了其对React性能优化的贡献以及在实际项目中的应用情况。文章涵盖了React Compiler的工作原理、关键特点和使用方法,并对相关hook的替代方案进行了说明。同时,文章还介绍了基础数据类型和引用数据类型的缓存方式及注意事项。

关键观点总结

关键观点1: React Compiler是React官方团队提供的优化性能的重要工具,能够实现元素级别的细粒度更新。

React Compiler通过自动缓存的方式来优化性能,对函数组件中声明或存在的所有值进行缓存,包括基础数据类型、引用数据类型和JSX。

关键观点2: React Compiler可以替代useRef、useCallback和useMemo等hook的使用,提高代码性能和开发体验。

由于React Compiler能够缓存引用数据类型和基础数据类型,因此在某些情况下可以不再使用useRef、useCallback和useMemo等hook。

关键观点3: 使用React Compiler时需要注意基础数据类型的修改不会导致缓存更新。

如果需要在交互过程中修改基础数据类型的值,需要将其转换为引用数据类型。

关键观点4: React Compiler具有很低的侵入性,对现有代码逻辑的影响非常小。

React Compiler的使用只需要简单的替换原有hook的写法,不需要大量修改代码逻辑。

关键观点5: React Compiler稳定性良好,值得尝试使用。

作者在实际项目中使用了React Compiler,并认为其稳定性非常好。


正文

React Compiler 是 React 官方团队提供的通过自动缓存的方式来优化性能的重要手段。他可以做到 元素级别的细粒度更新 。对于 React 性能优化掌握得不太好的小伙伴来说,这无疑是开发利器。

在刚开始接触 React Compiler 时,我明确表示了自己对于 Compiler 的抵触心理。这一抵触心里来源于对于 Compiler 的出现,到底会对代码逻辑造成什么样的影响的 不可控性

好在没过多久,我就彻底拿捏了 Compiler,对其工作原理有了比较深入的理解。当掌握了它之后,我对他的观念发生了转变,这确实非常好用。React Compiler 的侵入性非常弱,他对我们之前的代码逻辑几乎不会造成太大的影响,并且,我们可以拥有更好的开发体验。

在这个基础之上,我得出一个结论就是: useRef、useCallback、useMemo 都可以直接淘汰了。 我们的代码可以在保持优雅的同时,具备更好的性能。

具体的工作原理,大家可以通过查看这篇文章阅读

本文主要为大家介绍一下,弃用了这些hook 之后,在代码中的具体表示是什么样的。

React Compiler 并非 React 19 的专属,在我的付费小册 《React 19》 中专门为大家提供了如何在低版本中使用 Compiler 的方法,点击 文末阅读原文 ,可查看详情购买学习


一、思维调整,一切都会被缓存

React Compiler 会尝试缓存函数组件中声明或者存在的所有值。

这里的所有值,包括基础数据类型

let base = 20

引用数据类型,一个对象、一个函数等

const mp = {}

function handler({}

还包括 jsx。在 React 中,jsx 也是值的一种。

<div>b: {b}div>

由于默认被缓存,我们可以默认所有的引用类型,引用都是稳定不变的。因此,在这个前提之下, useMemo 也就可以不需要用了。

例如一个耗时计算,在之前我们使用 useMemo

// 之前
const d = useMemo(() => {
  const s = performance.now()
  while (performance.now() - s 1000) {
    //
  }
  return 20
}, [])
function cal({
  const s = performance.now()
  while (performance.now() - s 1000) {
    //
  }
  return 20
}

const d = cal()

同样的道理,我们之前使用的 useCallback 也可以不再使用了

// 之前
const handler = useCallback(() => {}, [])
// 现在
const  handler = () => {}

如果在函数中,存在前置的依赖条件,我们也不需要担心,Compiler 会自动识别依赖项,并在依赖项更新时重新创建函数

// 之前
const handler = useCallback(() => {
  ...
}, [counter])
// 现在
const handler = () => {
  ...
}

二、引用数据类型

我们要记住的是,缓存的是一个引用,因此,当我们声明一个引用数据类型时,具体的表现是,引用类型的引用不会被改变,但是里面的值可以被改变。

const a = {value20}

我们可以再其他操作中修改 a.value 的值,代码如下

function handler({
  a.value +=  1
  setB(b + 1)
  console.log('a.value: ', a.value)
}

演示效果为

有了这个效果之后,我们就可以完整的使用如下方式替代 useRef

基础数据类型的转化

// 现在
+ const a = {current: 20}

// 以前
- const a = useRef(20)

这样做的好处就是使用更透明与自由,不需要遵循额外的规则。当我们要缓存的本身就是对象时,会更简单直接。

// 以前
const mp = useRef({ title1text'hello woled' })

mp.current.title
// 现在
const mp = { title1text'hello woled' }

mp.title

三、基础数据类型

基础数据类型也可以被缓存

let base = 20

但是需要注意的是,如果我们在交互的过程中,修改了这个值,修改之后的值不会被缓存。这和基础数据类型的不可变性有直接的关系,使用时一定要注意。

let base = 20

// 点击时 修改 base
function handler({
  a.value +=  1
  setB(b + 1)
  base = base + 1
}

console.log('base: ', base)






请到「今天看啥」查看全文