国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

一文帶你搞懂react hooks的類(lèi)型聲明

瀏覽:3日期:2022-06-12 18:01:49
目錄node_modules中的@types是什么?types查找規(guī)則模塊types*.d.ts是什么useContextuseStateuseRefuseEffectuseLayoutEffectuseReduceruseCallbackuseMemouseImperativeHandle總結(jié)

在了解react hooks的類(lèi)型之前,有必要先了解一下@types、.d.ts文件的概念及作用。

node_modules中的@types是什么?

當(dāng)我們使用第三方npm包的時(shí)候,如果這個(gè)包不是ts編寫(xiě),則沒(méi)有導(dǎo)出類(lèi)型,這時(shí)候如果在ts中導(dǎo)入會(huì)報(bào)錯(cuò)。比如jquery 這時(shí)會(huì)報(bào)錯(cuò)

無(wú)法找到模塊“jquery”的聲明文件嘗試使用 npm i --save-dev @types/jquery (如果存在),或者添加一個(gè)包含 declare module 'jquery'; 的新聲明(.d.ts

這里提示找不到j(luò)query的類(lèi)型定義 可以安裝@types/jquery或者在d.ts中自定義類(lèi)型,大多數(shù)情況我們應(yīng)該使用第一種辦法,如果這個(gè)庫(kù)沒(méi)有@types庫(kù)再使用第二種。

types查找規(guī)則

當(dāng)我們使用import xx from時(shí)ts將會(huì)默認(rèn)從./node_modules/@types中獲取類(lèi)型聲明,具體查找規(guī)則是ts編譯器先在當(dāng)前編譯上下文找jquery的定義,找不到則再去./node_modules/@types中查找。 在本地模塊查找的類(lèi)型聲明作用域是在模塊,在@types中的類(lèi)型聲明是全局的。在tsconfig.json中也可以使用 typeRoots設(shè)置默認(rèn)路徑 。

模塊types

當(dāng)然在`tsconfig.json`中也可以使用`types`單獨(dú)控制`@types`。`types`指定的包會(huì)被單獨(dú)引入。這樣全局引入就失效了。

*.d.ts是什么

@types下存放的文件都是.d.ts開(kāi)頭的文件 對(duì)應(yīng)的npm包js的類(lèi)型聲明。 在.d.ts文件中聲明的類(lèi)型或者模塊,在其他文件中不需要使用import導(dǎo)入,可以直接使用,d.ts的類(lèi)型聲明可以自行編寫(xiě)也可以使用工具聲明。有2個(gè)工具

可以使用微軟的dts-gen,生成單個(gè)文件的聲明dtsmake。值得注意的是如果你使用JSDOC語(yǔ)法 在ts3.7以后是可以通過(guò)命令為js生成.ds文件。具體用法可查看TypeScript: Documentation - Creating .d.ts Files from .js files (typescriptlang.org)

介紹完前菜 現(xiàn)在開(kāi)始進(jìn)入本文正題。 一起來(lái)看下react hooks相關(guān)的類(lèi)型聲明吧。在@types/react/index.d.ts文件中。

useContext

`useContext和createContext`是結(jié)合一起使用的

useContext定義: function useContext<T>(context:Context<T>):TcreateContext定義: function createContext<T>(defaultValue:T,):Context<T> createContext的返回Context類(lèi)型的值提供給useContext的參數(shù)。這里泛型T在2個(gè)方法中是一致的,如果不指定 ts會(huì)類(lèi)型推導(dǎo)出正確的類(lèi)型。而Context 類(lèi)型 則是一個(gè)interface

interface Context<T> { Provider: Provider<T>; Consumer: Consumer<T>; displayName?: string | undefined;}

`Provider` 擁有`value`和`children` `Consumer`擁有 `children` 類(lèi)型都是`ReactNode|undefined`。想想我們這react中使用`Context`傳值 是不是感覺(jué)很熟悉?看懂類(lèi)型定義 再也不怕忘記api了。

useState

定義:function useState<S>(initialState:S| (() =>S)): [S, Dispatch<SetStateAction<S>>] 泛型S表示state 是用來(lái)約束initialState類(lèi)型,也可以傳入返回值是S的方法。 useState返回值為2個(gè)元素的元組類(lèi)型,返回state和更新state的方法。默認(rèn)情況下useState會(huì)根據(jù)傳入類(lèi)型自動(dòng)推導(dǎo)出S類(lèi)型。 SetStateAction<S>定義了傳入setState的參數(shù)類(lèi)型。是S類(lèi)型或者返回S類(lèi)型值的函數(shù)的聯(lián)合類(lèi)型。SetStateAction 的定義為: type SetStateAction<S> = S|((prevState:S) =>S),prevState為上一次的state,聯(lián)合類(lèi)型暫可以理解成或的關(guān)系。而 Dispatch 表示setState的類(lèi)型,是一個(gè)沒(méi)有返回值的方法。定義也很簡(jiǎn)單Dispatch :type Dispatch<A> = (value:A) =>void。 還有useState參數(shù)個(gè)數(shù)為0的情況。上面的類(lèi)型無(wú)法滿足,所以后面?zhèn)€函數(shù)重載約束沒(méi)有傳入初始值的實(shí)現(xiàn)。 function useState<S=undefined>(): [S|undefined, Dispatch<SetStateAction<S|undefined>>];

useRef

定義比較簡(jiǎn)單:function useRef<T>(initialValue:T):MutableRefObject<T>, useRef 返回一個(gè)可變 ref 對(duì)象,其 .current 屬性初始化為傳遞的參數(shù)。MutableRefObject就是一個(gè)包含current:T的接口。值得注意的是 這里同樣用了函數(shù)重載,包括了initialValue沒(méi)有傳或者為null的情況。ref在props中大部分的初始值都為null。 類(lèi)型聲明中注釋明確指定了如果要使用可變的useRef 則需要在范型參數(shù)中包含| null.

* Usage note: if you need the result of useRef to be directly mutable, include `| null` in the type * of the generic argument.

如果我們這樣寫(xiě),此時(shí)ref為RefObject類(lèi)型 RefObject的current被readonly修飾。所以是不可變的。當(dāng)在范型中指定了| null 則根據(jù)函數(shù)重載命中第一種類(lèi)型,返回MutableRefObject是可變的。

const ref = useRef<number>(null)ref.current = 2 // 無(wú)法分配到 'current' ,因?yàn)樗侵蛔x屬性。// 此時(shí)命中的這個(gè)重載的useReffunction useRef<T>(initialValue: T|null): RefObject<T>;useEffect

定義: function useEffect(effect:EffectCallback, deps?:DependencyList):void, EffectCallback是一個(gè)只能返回void|Destructor的函數(shù)類(lèi)型 用來(lái)處理副作用 。 void表示沒(méi)有返回值 ,但這里并不意味著你賦值一個(gè)有返回值的函數(shù)會(huì)報(bào)錯(cuò),在一個(gè)返回值為void的函數(shù)你明確返回類(lèi)型 并不會(huì)報(bào)錯(cuò)。而void真正表示無(wú)論你返回什么?編譯器都不會(huì)使用檢查它。 Destructor 表示析構(gòu)函數(shù),看下它的定義

declare const UNDEFINED_VOID_ONLY: unique symbol;type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never }

這里UNDEFINED_VOID_ONLY表示一個(gè)常量類(lèi)型 unique symbol是symbol的子類(lèi)型 , 使用unique symbol的變量必須為const,而值為never表示的是那些永不存在的值的類(lèi)型。 never 類(lèi)型是那些總是會(huì)拋出異常或根本就不會(huì)有返回值的函數(shù)表達(dá)式或箭頭函數(shù)表達(dá)式的返回值類(lèi)型。這里使用void和{ [UNDEFINED_VOID_ONLY]: never }作為聯(lián)合類(lèi)型, 明確約束了effect是不能有返回類(lèi)型的, 如果明確聲明 則會(huì)報(bào)錯(cuò)。 如果有async修飾函數(shù)默認(rèn)返回promise類(lèi)型, 所以在useEffect中的effect也同樣不能使用async。deps是可選參數(shù),作為依賴是一個(gè)只讀數(shù)組。ReadonlyArray是一個(gè)真正的只讀數(shù)組類(lèi)型,根據(jù)范型來(lái)約束數(shù)組元素類(lèi)型。它沒(méi)有改變數(shù)組的方法push shift等。

useLayoutEffect

useLayoutEffect類(lèi)型聲明與useEffect一致。但useLayoutEffect的callback會(huì)在DOM更新后同步觸發(fā) 在瀏覽器同步刷新之前執(zhí)行完成 可能會(huì)阻塞瀏覽器渲染。

useReducer

官方介紹useReducer 為 An alternative to useState.是useState的替代解決方案。一般我們都這樣使用。當(dāng)state結(jié)構(gòu)或邏輯比較復(fù)雜時(shí),用useReducer管理更方便容易。

function reducer(state, action) { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; default: throw new Error(); }}const [state, dispatch] = useReducer(reducer, {count: 0});state.countdispatch({type: 'decrement'})

在類(lèi)型聲明文件中useReducer寫(xiě)了5個(gè)重載函數(shù)類(lèi)型。

type ReducerWithoutAction<S> = (prevState: S) => S;type ReducerStateWithoutAction<R extends ReducerWithoutAction<any>> =R extends ReducerWithoutAction<infer S> ? S : never;function useReducer<R extends ReducerWithoutAction<any>, I>(reducer: R,initializerArg: I,initializer: (arg: I) => ReducerStateWithoutAction<R> ): [ReducerStateWithoutAction<R>, DispatchWithoutAction];第一種是reducer函數(shù)沒(méi)有傳action的情況。R表示reducer函數(shù)類(lèi)型, 其中參數(shù)state類(lèi)型和返回類(lèi)型必須一致。initializerArg表示初始參數(shù),類(lèi)型為泛型的第二個(gè)參數(shù)。initializer定義稍微復(fù)雜,但是其實(shí)約束了此類(lèi)型必須是一個(gè)參數(shù)為initializerArg類(lèi)型 返回值也同initializerArg類(lèi)型一致的參數(shù)類(lèi)型。而這個(gè)initializerArg就是reducer的參數(shù)state類(lèi)型。ReducerStateWithoutAction就是為了約束這三個(gè)參數(shù)的類(lèi)型。舉個(gè)例子更清晰. 下述代碼reducer中state initializerArg 已經(jīng) initializer的參數(shù)和返回參數(shù)類(lèi)型都應(yīng)該保持一致。type stateType = {num: number}function reducer(state: stateType) { return state}const [state,dispatch]=useReducer<typeof reducer,stateType>( reducer, {num: 0},state=>{ return {num: state.num+1} })

這里的extends 條件類(lèi)型是一種條件表達(dá)式進(jìn)行類(lèi)型的關(guān)系檢測(cè),類(lèi)似于三元表達(dá)式。意思為左側(cè)類(lèi)型可分配給右側(cè)類(lèi)型則返回?后面的類(lèi)型 否則返回:后的類(lèi)型。 而infer關(guān)鍵字只能出現(xiàn)在條件類(lèi)型extends 判斷為true的分支,表示一個(gè)待推斷的類(lèi)型,infer S表示將推斷的類(lèi)型保存在S中。

第二個(gè)重載與第一個(gè)類(lèi)似 只是在initializer為undefined的情況。如果在useReducer的泛型中指定了第二個(gè)參數(shù),則命中第一個(gè)重載 此時(shí)會(huì)報(bào)錯(cuò)。具體實(shí)現(xiàn)類(lèi)似下述代碼。function useReducer<R extends ReducerWithoutAction<any>>(reducer: R,initializerArg: ReducerStateWithoutAction<R>,initializer?: undefined ): [ReducerStateWithoutAction<R>, DispatchWithoutAction];type stateType = {num: number}function reducer(state: stateType) { return state}const [state,dispatch]=useReducer<typeof reducer>(reducer, {num: 0})第三個(gè)重載約束了reducer函數(shù)傳入action的情況,不同于redux action是any類(lèi)型。initializerArg初始參數(shù)為 state與泛型I的交叉類(lèi)型。I可能是state的子集的情況。ReducerState同樣是為了取出reducer中state類(lèi)型。initializer同上述第一種重載類(lèi)似。要約束arg initializerArg 一致。而初始initializer的返回值要與reducer中state一致。// Unlike redux, the actions _can_ be anythingtype Reducer<S, A> = (prevState: S, action: A) => S;// types used to try and prevent the compiler from reducing S// to a supertype common with the second argument to useReducer()type ReducerState<R extends Reducer<any, any>> = R extends Reducer<infer S, any> ? S : never;function useReducer<R extends Reducer<any, any>, I>(reducer: R,initializerArg: I & ReducerState<R>,initializer: (arg: I & ReducerState<R>) => ReducerState<R> ): [ReducerState<R>, Dispatch<ReducerAction<R>>];

舉個(gè)例子 初始參數(shù)initializer的state類(lèi)型 在初始函數(shù)的參數(shù)類(lèi)型也應(yīng)該一致。

// 代碼實(shí)現(xiàn)type stateType = {num: number}type actionType = { type: string, payload: number}function reducer(state: stateType,action: actionType) { if(action.type=='add'){ return {num: state.num+1} }else { return {num: state.num-1} }}const [state,dispatch]=useReducer<typeof reducer,actionType>(reducer, { type: 'add', payload: 1,num: 2},state=>{ return {num:state.num+state.payload}})第4個(gè)重載 和第三個(gè)類(lèi)似 在初始參數(shù)不包括state的情況, 初始參數(shù)initializer的state類(lèi)型 在初始函數(shù)的參數(shù)類(lèi)型也應(yīng)該一致。function useReducer<R extends Reducer<any, any>, I>(reducer: R,initializerArg: I,initializer: (arg: I) => ReducerState<R> ): [ReducerState<R>, Dispatch<ReducerAction<R>>];

第5個(gè)重載 和上述類(lèi)似 約束了initializer為undefined,reducer存在actions的情況

function useReducer<R extends Reducer<any, any>>(reducer: R,initialState: ReducerState<R>,initializer?: undefined ): [ReducerState<R>, Dispatch<ReducerAction<R>>];

useReducer的返回值都是一致。返回reducerState和Dispatch,而type Dispatch<A> = (value:A) =>void;就是一個(gè)沒(méi)有返回值的函數(shù) 用來(lái)觸發(fā)action 改變r(jià)educerState。

useCallback

定義比較簡(jiǎn)單: function useCallback<T extends (...args:any[]) =>any>(callback:T, deps:DependencyList):T; 范型T為function類(lèi)型為第一個(gè)參數(shù)callback的類(lèi)型,第二個(gè)參數(shù)DependencyList與useEffect的依賴數(shù)組一致,都是一個(gè)只讀的數(shù)組。主要作用是用來(lái)緩存callback實(shí)例,當(dāng)傳遞給子組件方法時(shí)與React.memo 或者shouldComponentUpdate一起使用。

useMemo

定義也比較簡(jiǎn)單:

// allow undefined, but don't make it optional as that is very likely a mistakefunction useMemo<T>(factory: () => T, deps: DependencyList | undefined): T;

范型T為factory的返回值類(lèi)型。deps依賴為DependencyList和undefined的聯(lián)合類(lèi)型,這里會(huì)有提示允許deps為undefined,但不能是可選的 否則可能是個(gè)錯(cuò)誤。

useImperativeHandle

useImperativeHandle主要用來(lái)配合forwardRef自定義暴露給父組件數(shù)據(jù)的。一般用來(lái)父組件調(diào)用子組件方法或獲取子組件數(shù)據(jù)時(shí)使用。

function useImperativeHandle<T, R extends T>(ref: Ref<T>|undefined, init: () => R, deps?: DependencyList): void;interface RefObject<T> {readonly current: T | null; } // Bivariance hack for consistent unsoundness with RefObjecttype RefCallback<T> = { bivarianceHack(instance: T | null): void }['bivarianceHack'];type Ref<T> = RefCallback<T> | RefObject<T> | null;

泛型T為ref的current的類(lèi)型,R是第二個(gè)參數(shù)init方法的返回值,DependencyList同上述依賴數(shù)組一樣 不可變數(shù)組。可以這樣使用

const Child = React.forwardRef<{num: number}>((prop,ref)=>{ useImperativeHandle<{num: number}, {num: number}>(ref,()=>({ 'num': 1 })) return (<div>123</div>)})const Foo = ()=>{ const childRef = useRef<{num: number}|null>(null) useLayoutEffect(() => { console.log(childRef.current?.num) // 1 }, []) return <> <Child ref={childRef}/> </>}總結(jié)

本文根據(jù)閱讀@types/react下hook相關(guān)源碼入手,意在幫助大家熟悉常用hook以及類(lèi)型聲明 在開(kāi)發(fā)時(shí)能得心應(yīng)手 明白hooks的約束條件 更深入理解hook的功能。如上述內(nèi)容有錯(cuò)誤,請(qǐng)不吝指出

以上就是一文帶你搞懂react hooks的類(lèi)型聲明的詳細(xì)內(nèi)容,更多關(guān)于react hooks的類(lèi)型聲明的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
主站蜘蛛池模板: 韩国毛片 免费 | 欧美一区二区视频在线观看 | 露脸国产野战最新在线视频 | 欧美成人xxxx| 黄色视品 | 国产高清在线精品一区二区三区 | 日本理论片免费高清影视在线观看 | 久久午夜影视 | 亚洲日本高清成人aⅴ片 | 午夜国产高清精品一区免费 | 亚洲精品美女在线观看播放 | 99在线视频精品 | 国产成人亚洲日本精品 | 久久精品亚洲乱码伦伦中文 | 成人免费视频国产 | 亚洲精品高清在线观看 | 国产步兵社区视频在线观看 | 久草中文在线观看 | 美女视频黄色免费 | 日韩在线无 | 久久毛片网站 | 美国三级在线观看 | 一级做a爰片性色毛片中国 一级做a爰性色毛片 | 老司机亚洲精品影院 | 日本一级特大毛片 | 91免费看片 | 成人欧美一区二区三区 | 国产专区一区 | 一区二区三区高清在线 | 99精品国产综合久久久久 | a级毛片免费完整视频 | 人人99| 精品一区二区三区免费毛片爱 | 神马午夜视频 | 国内xxxx乱子另类 | 亚欧精品一区二区三区 | 日本aa级片 | 不卡一级aaa全黄毛片 | 免费国产成人高清在线看软件 | 亚洲免费网 | 大学生久久香蕉国产线观看 |