关于前端:不数不知道React已经有22个hook了

48次阅读

共计 2544 个字符,预计需要花费 7 分钟才能阅读完成。

大家好,我卡颂。

5 月 30 日刚好是React10 周年纪念日。

我棘手拉了下 React 最新代码,这一看不要紧,竟然曾经有 22 个 hook 了。

其中:

  • react包导出了 21 个
  • react-dom包导出了 1 个(useFormStatus

本文会从 React 这些年倒退脉络的角度,聊聊这些 hook 的作用。

欢送退出人类高质量前端交换群,带飞

时代的更迭

截止以后,React的倒退次要经验了 3 个期间:

  • CSR期间(客户端渲染期间)
  • 并发期间
  • RSC期间(服务端组件期间)

以后的 22 个 hook 也都是这 3 个期间的产物。

CSR期间

工夫回到 2013 年,为了解决 facebook 日益简单的交互,jordwalke开发了 React。通过一段时间摸索,React 逐步造成一套满足 CSR 的开发模式。

这套开发模式从 ClassComponent 迁徙到 FunctionComponent 后,便造成了最后的一批 hook。这些hook 都与 CSR 的开发模式相干。比方:

与状态的流转相干的:

  1. useState
  2. useReducer
  3. useContext

与解决副作用相干的:

  1. useEffect
  2. useLayoutEffect

与进步操作自由度相干的:

  1. useRef

与性能优化相干的:

  1. useMemo
  2. useCallback

与调试相干:

  1. useDebugValue

随着 React 继续迭代,又引入了几个 hook,实质来说他们都是为了欠缺CSR 的开发模式,对现有 hook 能力进行补充或束缚:

  1. useImperativeHandle(管制 useRef 避免其失控)
  2. useEffectEvent(对 useEffect 能力的补充)
  3. useInsertionEffect(对 useEffect 场景的补充)
  4. useMemoCache(缩小性能优化心智累赘)

这里简略聊聊 useMemoCache。长久以来,不论是ClassComponentshouldComponentUpdate,还是 FC 中 2 个性能优化相干hook,都存在比拟重的心智累赘,比方:

  • 开发者须要思考是否须要性能优化
  • 开发者须要思考何时应用useMemouseCallback

为了解决这个问题,在 2021 年的 React Conf,黄玄带来了 可能通过编译器生成等效于 useMemo、useCallback 代码 的计划 —— React Forget

useMemoCache就是 React 外部为 React Forget 提供缓存反对的hook

所以这个 hook 是给编译器用的,而不是咱们一般开发者。

并发期间

在 13 年诞生之初,React的作者 jordwalke 就指出 —— React将来会倒退 并发个性

这并不是什么高瞻远瞩的预言,React自身是个重运行时的框架,这意味着他的迭代方向须要围绕 运行时 开展。而 并发个性 是一种优良的运行时性能优化策略。

随着并发个性落地,首先推出的是 2 个并发相干hook

  1. useTransition
  2. useDeferredValue

这 2 个 hook 的实质都是升高更新的优先级,更新 意味着 视图渲染 ,所以当更新领有不同优先级后,这意味着 视图渲染 领有不同优先级。

这就是并发更新的实践根底。

然而,并发更新的呈现,突破了 React 因循多年的 一次更新对应一次渲染 的模式。

为了让现有的库兼容并发模式,推出了如下hook

  1. useMutableSource
  2. useSyncExternalStore

所以,上述 2 个 hook 次要是面向开源库作者。

RSC期间

RSC(服务端组件)是一个盛大的工程,他的实现不是欲速不达的,这一点从新出的 hook 就能看出。

既然是服务端组件,那就波及到组件在服务端渲染。那么,对于存在惟一标识(比方上面的id props)的组件,如何保障这个惟一标识在服务端与客户端统一呢?

<SomeCpn id={id}/>

如果组件仅在一端渲染,简略应用 Math.random() 就能取得惟一标识:

const id = Math.random();

<SomeCpn id={id}/>

但如果这段逻辑在服务端 / 客户端都运行一次,显然 id 就不惟一了。

为了生成在服务端 / 客户端惟一的id,有了:

  1. useId

在并发期间,因为引入了 渲染优先级 的概念,那势必存在一些因为优先级有余,而处于 pending 中的渲染。

如何展现 渲染的 pending 状态 呢?React引入了 <Suspense> 组件。

到了 RSC 期间,React团队发现,渲染的 pending 状态 pending数据申请的 pending 状态 不也是 pending 吗?

换言之,任何须要两头 pending 状态的流程,不都能够纳入 <Suspense> 的治理范畴?

那该怎么标记一个流程能够被纳入 <Suspense> 的治理呢?于是有了:

  1. use

通过这个 hook 申明的流程中的 pending 状态都会被纳入 <Suspense> 的治理。

既然 <Suspense> 越来越重要,那咱们是不是要针对他做些优化?既然 <Suspense> 能够在不同视图之间切换,那为他减少缓存显然是种不错的优化形式,于是有了:

  1. useCacheRefresh(用于建设 <Suspense> 缓存)

到这一步,RSC的基础设施算是搭好了,下一步该构建下层利用了。

在浏览器端,与 RSC 理念最符合的便是 form 标签,围绕 form 标签的 action 属性,React推出了如下hook

  1. useOptimistic
  2. useFormStatus

这 2 个 hook 都是为了优化 表单提交 这一场景(也能够说是 RSC 与客户端的交互场景)。

对于这 2 个hook,更具体的解释能够参考 form 元素是 React 的将来一文

总结

如果说 CSR 期间的 hook 都是面向开发者间接应用的。那么并发期间最后的 2 个 hookuseTransitionuseDeferredValue)曾经鲜有开发者应用了,而前期相似useMutableSource 这样的hook,一般开发者则基本用不到。

同样的,再往后的 RSC 期间的所有hook,一般开发者都用不到。他们都是为其余库、框架(比方Next.js)提供的。

这标记着 React 倒退方向的一直变动:

  • 晚期,定位是前端框架,次要为了解决 facebook 本身问题,顺便开源,受众是开发者
  • 中期,定位是底层 UI 库,受众是开源库作者
  • 以后,定位是 web 底层操作系统,受众是下层全栈框架

正文完
 0