ahooks源码分析之usePrevious

点击上方 前端瓶子君,关注公众号

回复算法,加入前端编程面试算法每日一题群

来源:倒影

https://juejin.cn/post/6952118323559530504

usePrevious用于保存上一次渲染时的状态。

React官方文档提供了一个实现:

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}
复制代码

usePrevious记录的值初始为空,每轮渲染后记录状态值,这样每次渲染返回的便是上一轮渲染时的值。

react-use同样使用了此实现。

ahooks则为用户提供了compare,可以让用户决定是否更新usePrevious记录的值。

import { useRef } from 'react';

export type compareFunction<T> = (prev: T | undefined, next: T) => boolean;

function usePrevious<T>(state: T, compare?: compareFunction<T>): T | undefined {
  const prevRef = useRef<T>();
  const curRef = useRef<T>();

  const needUpdate = typeof compare === 'function' ? compare(curRef.current, state) : true;
  if (needUpdate) {
    prevRef.current = curRef.current;
    curRef.current = state;
  }

  return prevRef.current;
}

export default usePrevious;
复制代码

ahooks 使用了两个ref,一个记录当前值,一个记录之前的值。不过为什么要这样实现呢?这样实现与react-use的实现方式有什么不同?????

在一番试验无果后,随意搜索了下却找到了这个issue

什么?ahooks的实现不符合使用规范????

issue作者给出的链接中说明了在render时读取或修改ref的值时会进行警告,并且Dan在回复中说明了这样做的原因。

image.png

大意是在render时读取ref的值和读取一个随机的全局变量一样。读取的值是什么取决于何时调用render。如果React调用在稍微不同的时间渲染,可能会得到不同的结果。

在未来React默认开启Concurrent模式后,ahooks的实现便会出现问题。

issue作者除了给出解释之外,还提供了一个demo。demo中使用的usePreviousStrictMode下有了不同的行为。

不过demo中渲染用的也是legacy模式,那为什么在StrictMode下行为会不同?????

打断点调试了一番,发现进入页面时usePrevious居然被调用了两次,导致curRefpreRef记录的状态出现了问题。

在React issue中搜索StrictModetwice等关键字找到了原因,还是我们的Dan神回复的:

image.png

issue地址

使用了StrictMode且用了Hooks的组件会在开发模式时渲染两次。StrictMode的一个主要目的是方便将现有项目迁移到未来使用concurrent模式的React版本中,会这么设计不奇怪。

至此,作战告捷????

简单改了下ahooksusePrevious实现。

function usePrevious<T>(state: T, compare?: (prev: T | undefined, next: T) => boolean): T | undefined {
  const ref = useRef<T>();

  useEffect(() => {
    const needUpdate = typeof compare === 'function' ? compare(ref.current, state) : true;
    if (needUpdate) {
      ref.current = state;
    }
  });

  return ref.current;
}
复制代码

最后

欢迎关注【前端瓶子君】✿✿ヽ(°▽°)ノ✿

回复「算法」,加入前端编程源码算法群,每日一道面试题(工作日),第二天瓶子君都会很认真的解答哟!

回复「交流」,吹吹水、聊聊技术、吐吐槽!

回复「阅读」,每日刷刷高质量好文!

如果这篇文章对你有帮助,「在看」是最大的支持

》》面试官也在看的算法资料《《

“在看和转发”就是最大的支持

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值