首页 > 其他分享 >ahooks 源代码学习(一)

ahooks 源代码学习(一)

时间:2023-04-13 17:36:33浏览次数:45  
标签:set const defaultValue return 学习 useLatest ahooks 源代码 fn

无论人生上到哪一层台阶,阶下有人在仰望你,阶上亦有人在俯视你。你抬头自卑,低头自得,唯有平视,才能看见真正的自己。

ahooks 好久之前就知道,但是几乎不怎么使用,最近正在尝试使用一些,而且也对其中的一些简单的 hooks 的原理感兴趣,下面记录几个吧

1. 第一个当然是最简单的(由浅入深)useToggle

代码位置

// 泛型,接口类型参数D、R,其中defaultValue类型为D,默认值为false;reverseValue可选参数为R
function useToggle<D, R>(
  defaultValue: D = false as unknown as D,
  reverseValue?: R
) {
  // state类型为D、R的联合类型, 默认值为defaultValue, 不传则为false
  const [state, setState] = useState<D | R>(defaultValue);
  // actions是一个对象,可以修改state数据的行为对象
  const actions = useMemo(() => {
    // reverseValue不存在则为defaultValue取反,存在则为reverseValue
    const reverseValueOrigin = (
      reverseValue === undefined ? !defaultValue : reverseValue
    ) as D | R;
    // 判断当前值,取另一个值
    const toggle = () =>
      setState((s) => (s === defaultValue ? reverseValueOrigin : defaultValue));
    // 赋值state为传参的值
    const set = (value: D | R) => setState(value);
    const setLeft = () => setState(defaultValue);
    const setRight = () => setState(reverseValueOrigin);
    return {
      toggle,
      set,
      setLeft,
      setRight,
    };
    // useToggle ignore value change
    // }, [defaultValue, reverseValue]);
  }, []);

  return [state, actions];
}

由上面源码可知,使用这个 hooks 时需要注意两个事情:

  • 当 defaultValue 不是 boolean 值时, 注意一定要传第二个参数,不然使用 setRight 和 toggle 取反时,会出现问题
  • 使用 set 方法时,value 时 D、R 的联合类型,如果不给 useToggle 传递泛型参数,比如'a'和'b'就会自动推断成 string,传参是不会进行严格校验,所以注意需要给 useToggle 传递泛型参数

2. useBoolean

代码位置

export default function useBoolean(defaultValue = false): [boolean, Actions] {
  const [state, { toggle, set }] = useToggle(defaultValue);

  const actions: Actions = useMemo(() => {
    const setTrue = () => set(true);
    const setFalse = () => set(false);
    return {
      toggle,
      set: (v) => set(!!v),
      setTrue,
      setFalse,
    };
  }, []);

  return [state, actions];
}

就是useToggle中的方法,而且限制了 defaultValue 的类型为 boolean 类型

3. useMount

代码位置

const useMount = (fn: () => void) => {
  if (process.env.NODE_ENV === "development") {
    if (!isFunction(fn)) {
      console.error(
        `useMount: parameter \`fn\` expected to be a function, but got "${typeof fn}".`
      );
    }
  }
  useEffect(() => {
    fn?.();
  }, []);
};

就是这么一段,在 useEffect 中执行传入的这个 fn

useLatest

代码位置

import { useRef } from "react";

function useLatest<T>(value: T) {
  const ref = useRef(value);
  ref.current = value;

  return ref;
}

export default useLatest;

这里代码看我上一篇文章hooks 闭包陷阱有比较好的解释

useUnmount

代码位置

import { useEffect } from "react";
import useLatest from "../useLatest";
import { isFunction } from "../utils";

const useUnmount = (fn: () => void) => {
  if (process.env.NODE_ENV === "development") {
    if (!isFunction(fn)) {
      console.error(
        `useUnmount expected parameter is a function, got ${typeof fn}`
      );
    }
  }
  const fnRef = useLatest(fn);
  useEffect(
    () => () => {
      fnRef.current();
    },
    []
  );
};
export default useUnmount;

看代码可以发现,useUnmount 中使用了 useLatest, 但是我产生一个疑问,为什么 useMount 就不使用 useLatest 呢? 首先说一下什么要使用 useLatest,看下面的例子

const App = () => {
  const [count, setCount] = useState(0);
  // 如果是这样,就获取不到最新值。
  useEffect(() => {
    return () => {
      console.log("点击次数", count);
    };
  }, []);

  return (
    <>
      点击次数:{count}
      <Button
        type="primary"
        onClick={() => {
          setCount(count + 1);
        }}
      >
        +1
      </Button>
    </>
  );
};

点击几次,然后离开这个组件的时候,打印的 count 还是 0,原因还是之前的闭包陷阱的问题,但是有时我们卸载的时候需要用到 state,所以通过 useLatest(fn),每次都可以获取到最新的值,避免闭包陷阱的问题,但是 useMount 为什么不使用呢?

我尝试了一次,当你在 useMount 里面写一个定时器,它每次输出的 count 永远是 0,也是闭包陷阱的问题,但是我想会不会在 useMount 执行时,我只有在里面存在定时器时才会出现使用 count 的情况,所以不需要呢,而且当里面存在定时器我直接使用 useLatest 会不会更好呢,没准也是使用场景小,所以不增加吧(个人想法) 演示示例

unmountedRef

代码位置

import { useEffect, useRef } from "react";

const useUnmountedRef = () => {
  const unmountedRef = useRef(false);
  useEffect(() => {
    unmountedRef.current = false;
    return () => {
      unmountedRef.current = true;
    };
  }, []);
  return unmountedRef;
};

export default useUnmountedRef;

这个 hooks 作用就是获取当前组件是否已经卸载,看代码可知使用 unmountedRef 存储这个变量,在 useEffect 的两个阶段去修改这个值,然后返回出去

总结

这篇文章主要分析两点,其余都是通过这两点拓展出来的,一个是 useToggle, 另一个是 useLatest,希望对大家有帮助,后续解读其他的 hooks

标签:set,const,defaultValue,return,学习,useLatest,ahooks,源代码,fn
From: https://blog.51cto.com/u_16070219/6188263

相关文章

  • 低代码平台源代码交付的重要性,别再傻傻被骗了……
    一、前言作为这两年IT界的风口,低代码在众人眼里已经不是什么陌生的概念。对标于传统的纯代码开发,低代码是一种快速开发软件(应用程序)的方法,平台通过对大量功能与场景做提前封装,使得用户可以在可视化的基础上,通过拖拉拽就能完成开发,手动编码非常少。这种可视化的开发大大方便了开......
  • springboot学习之四(整和mybatis)
    springboot整和mybatis    1.mapper文件开发 2.纯注解开发    https://www.cnblogs.com/fps2tao/p/13821490.html ......
  • mysql创建百万条虚假数据进行学习
    1.创建基础表CREATETABLE`app_user`(`id`bigint(20)unsignedNOTNULLAUTO_INCREMENT,`name`varchar(50)DEFAULT''COMMENT'用户昵称',`email`varchar(50)NOTNULLCOMMENT'用户邮箱',`phone`varchar(20)DEFAULT'......
  • springboot学习之三(整个redis)
     springboot整合redis1.依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>2.配置#Redis配置spring.r......
  • Python网络爬虫学习实战:爬虫快速入门
    很多同学私信问爬虫的相关教程,想了想,还是专门跟大家出些Python爬虫学习相关的教程,从零开始阐述如何编写Python网络爬虫,以及网络爬虫中容易遇到的问题,比如具有反爬加密的网站,还有爬虫拿不到数据,以及登录验证等问题,会伴随大量网站的爬虫实战来进行。我们编写网络爬虫最主要的目的是爬......
  • 2-安全学习防火墙篇-UTM-防病毒
    1.模拟器没有licence2.licence管理(可以给厂商购买)正常会给licence如下激活licence文档:https://support.huawei.com/hedex/hdx.do?docid=EDOC1100149311&id=ZH-CN_XTASK_0178408849激活后如下3.打开生产防火墙查看3.配置UTM防病毒如图默认的配置4.UTM入侵防御......
  • PyTorch深度学习建模与应用--每日最高温度预测
    1.python2.JupyterLabhttp://jupyter.org/安装jupyterlab只需要在命令提示符中输入pipinstalljupyterlab启动则在命令提示符中输入jupyterlabhttps://jupyter.org/try-jupyter/lab/  可以在这里进行尝试。3.PyTorchpytorch的配置可以看这篇https://blog.csdn.net/m0_7257......
  • 跟随 三维地图看世界 学习
    文档说明:只记录关键地方;2023-04-11缘由:搜索知识,但是搜索引擎不太好用,索性记录一下笔记:收藏目录:中国人,如何给公路起名字?果敢、佤邦、掸邦之间什么关系?对“降准”和“降息”区别中国村庄的名字,从何而来?湾、楼、沟、塘、店各不相同!这10年,中国修了哪些基建工程?【2012-202......
  • sass学习
    变量Sass使用$符号来标识变量上面我们声明了一个名为$highlight-color的变量,我们可以把该变量用在任何位置以空格分割的多属性值也可以标识标量变量范围与css属性不同,变量可以在css规则块定义之外存在。当变量定义在css规则块内,那么该变量只能在此规则块内使用。如果它们出现在任......
  • 跟随 钛科普 学习
    文档说明:只记录关键地方;2023-04-11缘由:搜索知识,但是搜索引擎不太好用,记录一下笔记:收藏目录:受电弓如何与接触网亲密接触而互不伤害......