不清楚React Hooks的类型声明?来看就对了

在了解react hooks的类型之前,有必要先了解一下@types、.d.ts文件的概念及作用。,当我们使用第三方npm包的时候,如果这个包不是ts编写,则没有导出类型,这时候如果在ts中导入会报错。比如jquery 这时会报错,无法找到模块“jquery”的声明文件尝试使用 npm i –save-dev @types/jquery (如果存在),或者添加一个包含 declare module ‘jquery’; 的新声明(.d.ts,这里提示找不到jquery的类型定义 可以安装@types/jquery或者在d.ts中自定义类型,大多数情况我们应该使用第一种办法,如果这个库没有@types库再使用第二种, 可以在https://microsoft.github.io/TypeSearch/中查找一个包是否存在types。,当我们使用import xx from时ts将会默认从./node_modules/@types中获取类型声明,具体查找规则是ts编译器先在当前编译上下文找jquery的定义,找不到则再去./node_modules/@types中查找。 在本地模块查找的类型声明作用域是在模块,在@types中的类型声明是全局的。在tsconfig.json中也可以使用typeRoots设置默认路径 。,可以使用微软的dts-gen,生成单个文件的声明dtsmake。值得注意的是如果你使用JSDOC语法 在ts3.7以后是可以通过命令为js生成.ds文件。具体用法可查看官方文档。,介绍完前菜,现在开始进入本文正题。 一起来看下react hooks相关的类型声明吧。在@types/react/index.d.ts文件中。,useContext定义: function useContext<T>(context:Context<T>):TcreateContext定义: function createContext<T>(defaultValue:T,):Context<T>createContext的返回Context类型的值提供给useContext的参数。这里泛型T在2个方法中是一致的,如果不指定 ts会类型推导出正确的类型。而Context 类型 则是一个interface,定义:function useState<S>(initialState:S| (() =>S)): [S, Dispatch<SetStateAction<S>>]泛型S表示state 是用来约束initialState类型,也可以传入返回值是S的方法。useState返回值为2个元素的元组类型,返回state和更新state的方法。默认情况下useState会根据传入类型自动推导出S类型。SetStateAction<S>定义了传入setState的参数类型。是S类型或者返回S类型值的函数的联合类型。SetStateAction 的定义为: type SetStateAction<S> = S|((prevState:S) =>S),prevState为上一次的state,联合类型暂可以理解成或的关系。而 Dispatch 表示setState的类型,是一个没有返回值的方法。定义也很简单Dispatch :type Dispatch<A> = (value:A) =>void。 还有useState参数个数为0的情况。上面的类型无法满足,所以后面个函数重载约束没有传入初始值的实现。function useState<S=undefined>(): [S|undefined, Dispatch<SetStateAction<S|undefined>>];,定义比较简单:function useRef<T>(initialValue:T):MutableRefObject<T>, useRef 返回一个可变 ref 对象,其 .current 属性初始化为传递的参数。MutableRefObject就是一个包含current:T的接口。值得注意的是 这里同样用了函数重载,包括了initialValue没有传或者为null的情况。ref在props中大部分的初始值都为null。 类型声明中注释明确指定了如果要使用可变的useRef 则需要在范型参数中包含| null.,如果我们这样写,此时ref为RefObject类型 RefObject的current被readonly修饰。所以是不可变的。当在范型中指定了| null 则根据函数重载命中第一种类型,返回MutableRefObject是可变的。,定义: function useEffect(effect:EffectCallback, deps?:DependencyList):void, EffectCallback是一个只能返回void|Destructor的函数类型 用来处理副作用 。 void表示没有返回值 ,但这里并不意味着你赋值一个有返回值的函数会报错,在一个返回值为void的函数你明确返回类型 并不会报错。而void真正表示无论你返回什么?编译器都不会使用检查它。 Destructor 表示析构函数,看下它的定义,这里UNDEFINED_VOID_ONLY表示一个常量类型 unique symbol是symbol的子类型 , 使用unique symbol的变量必须为const,而值为never表示的是那些永不存在的值的类型。 never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。这里使用void和{ [UNDEFINED_VOID_ONLY]: never }作为联合类型, 明确约束了effect是不能有返回类型的, 如果明确声明 则会报错。 如果有async修饰函数默认返回promise类型, 所以在useEffect中的effect也同样不能使用async。deps是可选参数,作为依赖是一个只读数组。ReadonlyArray是一个真正的只读数组类型,根据范型来约束数组元素类型。它没有改变数组的方法push shift等。,useLayoutEffect类型声明与useEffect一致。但useLayoutEffect的callback会在DOM更新后同步触发 在浏览器同步刷新之前执行完成 可能会阻塞浏览器渲染。,官方介绍useReducer 为 An alternative to useState.是useState的替代解决方案。一般我们都这样使用。当state结构或逻辑比较复杂时,用useReducer管理更方便容易。,在类型声明文件中useReducer写了5个重载函数类型。,这里的extends 条件类型是一种条件表达式进行类型的关系检测,类似于三元表达式。意思为左侧类型可分配给右侧类型则返回?后面的类型 否则返回:后的类型。 而infer关键字只能出现在条件类型extends 判断为true的分支,表示一个待推断的类型,infer S表示将推断的类型保存在S中。,举个例子 初始参数initializer的state类型 在初始函数的参数类型也应该一致。,第5个重载 和上述类似 约束了initializer为undefined,reducer存在actions的情况,useReducer的返回值都是一致。返回reducerState和Dispatch,而type Dispatch<A> = (value:A) =>void;就是一个没有返回值的函数 用来触发action 改变reducerState。,定义比较简单:function useCallback<T extends (…args:any[]) =>any>(callback:T, deps:DependencyList):T;范型T为function类型为第一个参数callback的类型,第二个参数DependencyList与useEffect的依赖数组一致,都是一个只读的数组。主要作用是用来缓存callback实例,当传递给子组件方法时与React.memo 或者shouldComponentUpdate一起使用。,定义也比较简单:,范型T为factory的返回值类型。deps依赖为DependencyList和undefined的联合类型,这里会有提示允许deps为undefined,但不能是可选的 否则可能是个错误。,useImperativeHandle主要用来配合forwardRef自定义暴露给父组件数据的。一般用来父组件调用子组件方法或获取子组件数据时使用。,泛型T为ref的current的类型,R是第二个参数init方法的返回值,DependencyList同上述依赖数组一样 不可变数组。可以这样使用,本文根据阅读@types/react下hook相关源码入手,意在帮助大家熟悉常用hook以及类型声明,在开发时能得心应手,明白hooks的约束条件,更深入理解hook的功能。

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/29538.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年6月23日
下一篇 2023年7月15日