TypeScript在React項(xiàng)目中的使用實(shí)踐總結(jié)
序言
本文會(huì)側(cè)重于TypeScript(以下簡(jiǎn)稱(chēng)TS)在項(xiàng)目中與React的結(jié)合使用情況,而非TS的基本概念。關(guān)于TS的類(lèi)型查看可以使用在線(xiàn)TS工具👉TypeScript游樂(lè)場(chǎng)
React元素相關(guān)
React元素相關(guān)的類(lèi)型主要包括ReactNode
、ReactElement
、JSX.Element
。
ReactNode
。表示任意類(lèi)型的React節(jié)點(diǎn),這是個(gè)聯(lián)合類(lèi)型,包含情況眾多;ReactElement/JSX
。從使用表現(xiàn)上來(lái)看,可以認(rèn)為這兩者是一致的,屬于ReactNode
的子集,表示“原生的DOM組件”或“自定義組件的執(zhí)行結(jié)果”。
使用示例如下:
const MyComp: React.FC<{ title: string; }> = ({title}) => <h2>{title}</h2>; // ReactNode const a: React.ReactNode = null || undefined || <div>hello</div> || <MyComp title="world" /> || "abc" || 123 || true; // ReactElement和JSX.Element const b: React.ReactElement = <div>hello world</div> || <MyComp title="good" />; const c: JSX.Element = <MyComp title="good" /> || <div>hello world</div>;
原生DOM相關(guān)
原生的 DOM 相關(guān)的類(lèi)型,主要有以下這么幾個(gè):Element
、 HTMLElement
、HTMLxxxElment
。
簡(jiǎn)單來(lái)說(shuō): Element = HTMLElement + SVGElement
。
SVGElement
一般開(kāi)發(fā)比較少用到,而HTMLElement
卻非常常見(jiàn),它的子類(lèi)型包括HTMLDivElement
、HTMLInputElement
、HTMLSpanElement
等等。
因此我們可以得知,其關(guān)系為:Element > HTMLElement > HTMLxxxElement
,原則上是盡量寫(xiě)詳細(xì)。
React合成事件相關(guān)
在 React 中,原生事件被處理成了React 事件,其內(nèi)部是通過(guò)事件委托來(lái)優(yōu)化內(nèi)存,減少DOM事件綁定的。言歸正傳,React 事件的通用格式為[xxx]Event,常見(jiàn)的有MouseEvent
、ChangeEvent
、TouchEvent
,是一個(gè)泛型類(lèi)型,泛型變量為觸發(fā)該事件的 DOM 元素類(lèi)型。
示例如下:
// input輸入框輸入文字 const handleInputChange = (evt: React.ChangeEvent<HTMLInputElement>) => { console.log(evt); }; // button按鈕點(diǎn)擊 const handleButtonClick = (evt: React.MouseEvent<HTMLButtonElement>) => { console.log(evt); }; // 移動(dòng)端觸摸div const handleDivTouch = (evt: React.TouchEvent<HTMLDivElement>) => { console.log(evt); };
與hooks的結(jié)合
在hooks中,并非全部鉤子都與TS有強(qiáng)關(guān)聯(lián),比如useEffect就不依賴(lài)TS做類(lèi)型定義,我們挑選比較常見(jiàn)的幾個(gè)和TS強(qiáng)關(guān)聯(lián)的鉤子來(lái)看看。
useState
如果初始值能說(shuō)明類(lèi)型,就不用給 useState 指明泛型變量;
// ❌這樣寫(xiě)是不必要的,因?yàn)槌跏贾?已經(jīng)能說(shuō)明count類(lèi)型 const [count, setCount] = useState<number>(0); // ✅這樣寫(xiě)好點(diǎn) const [count, setCount] = useState(0);
如果初始值是 null 或 undefined,那就要通過(guò)泛型手動(dòng)傳入你期望的類(lèi)型,并在訪(fǎng)問(wèn)屬性的時(shí)候通過(guò)可選鏈來(lái)規(guī)避語(yǔ)法錯(cuò)誤。
interface IUser { name: string; age: number; } const [user, setUser] = React.useState<IUser | null>(null); console.log(user?.name);
useRef
這個(gè) hook 比較特別,它通常有兩種用途:
用來(lái)連接 DOM,以獲取到 DOM 元素;
// 連接DOM,初始值賦值為null,不能是undefined,如要指明泛型變量需要具體到HTMLxxxElement // 如果我們確定inputRef.current在調(diào)用時(shí)一定是有值的,可以使用非空斷言,在null后添加! const inputRef = useRef<HTMLInputElement>(null!); const handleClick = () => { inputRef.current.focus(); // 當(dāng)然不用非空斷言,用inputEl.current?.focus()可選鏈也是可以的 } return ( <input ref={inputRef} /> <button onClick={handleClick}>點(diǎn)擊</button> )
2.用來(lái)存儲(chǔ)變量,由于是存儲(chǔ)在函數(shù)式組件的外部,比起 useState,它不會(huì)存在異步更新的問(wèn)題,也不會(huì)存在由capture-value
特性引發(fā)的過(guò)時(shí)變量的問(wèn)題,但是要注意賦值后由于ref引用沒(méi)變,不會(huì)引起重渲染。
// 通過(guò)初始值來(lái)自動(dòng)指明泛型變量類(lèi)型 const sum = useRef(0); // 通過(guò).current直接賦值 sum.current = 3; // 不存在異步更新問(wèn)題 console.log(sum.current); // 3
useSelector
useSelector用于獲取store中的狀態(tài),其第一個(gè)固定參數(shù)為函數(shù),函數(shù)的入?yún)⒓礊閟tore,而store的類(lèi)型RootState需要在store中提前定義好,一種常見(jiàn)的定義如下:
在store.ts中:
const store = createStore(rootReducer); export type RootState = ReturnType<typeof rootReducer>;
使用時(shí):
const { var1, var2 } = useSelector((store: RootState) => store.xxx);
自定義 hook
如果我們需要仿照 useState 的形式,返回一個(gè)數(shù)組出去,則需要在返回值的末尾使用as const,標(biāo)記這個(gè)返回值是個(gè)常量,否則返回的值將被推斷成聯(lián)合類(lèi)型。
const useInfo = () => { const [age, setAge] = useState(0); return [age, setAge] as const; // 類(lèi)型為一個(gè)元組,[number, React.Dispatch<React.SetStateAction<number>>] };
redux相關(guān)
對(duì)于action的定義,我們可以使用官方暴露的AnyAction,放寬對(duì)于action內(nèi)部鍵值對(duì)的限制,如下:
import { AnyAction } from "redux"; const DEF_STATE = { count: 0, type: 'integer' }; // 使用redux的AnyAction放寬限制 function countReducer(state = DEF_STATE, action: AnyAction) { switch (action.type) { case "INCREASE_COUNT": return { ...state, count: state.count + 1, }; case "DECREASE_COUNT": return { ...state, count: state.count - 1, }; default: return state; } } export default countReducer;
規(guī)約
子組件的入?yún)⒚麨閇組件名]Props,如:
// 比如當(dāng)前組件名為InfoCard export interface InfoCardProps { name: string; age: number; }
interface接口類(lèi)型以大寫(xiě)開(kāi)頭;
為后端接口的出入?yún)?shū)寫(xiě)interface,同時(shí)使用利于編輯器提示的jsdoc風(fēng)格做注釋?zhuān)纾?/p>
export interface GetUserInfoReqParams { /** 名字 */ name: string; /** 年齡 */ age: number; /** 性別 */ gender: string; }
其他
鍵名或鍵值不確定如何處理?
// 表示鍵名不確定,鍵值限制為number類(lèi)型 export interface NotSureAboutKey { [key: string]: number; } // 當(dāng)鍵名鍵值都不確定時(shí),以下接口對(duì)任何對(duì)象都是適用的 export interface AllNotSure { [key: string]: any; }
如何在接口中使用泛型變量?
所謂泛型,就是預(yù)定義類(lèi)型。它的目的是:達(dá)到類(lèi)型定義的局部靈活,提高復(fù)用性。我們通常會(huì)在接口中使用泛型,如:
// 通常,我們會(huì)為接口的泛型變量指定一個(gè)默認(rèn)類(lèi)型 interface IHuman<T = unknown> { name: string; age: number; gender: T; } // 其他地方使用時(shí) const youngMan: IHuman<string> = { name: 'zhangsan', age: 18, gender: 'male' }
到此這篇關(guān)于TypeScript在React項(xiàng)目中的使用總結(jié)的文章就介紹到這了,更多相關(guān)TypeScript在React使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React 事件綁定的實(shí)現(xiàn)及區(qū)別
事件綁定也是其中一部分內(nèi)容,通過(guò)事件委托和事件合成,React 在內(nèi)部對(duì)事件進(jìn)行優(yōu)化和處理,減少了事件處理函數(shù)的調(diào)用次數(shù),從而提升了性能,本文主要介紹了React事件綁定的實(shí)現(xiàn)及區(qū)別,感興趣的可以了解一下2024-03-03使用React封裝一個(gè)Tree樹(shù)形組件的實(shí)例代碼
這篇文章主要介紹了使用React封裝一個(gè)Tree樹(shù)形組件的實(shí)例,文中通過(guò)代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-03-03react-pdf實(shí)現(xiàn)將pdf文件轉(zhuǎn)為圖片,用于頁(yè)面展示
這篇文章主要介紹了react-pdf實(shí)現(xiàn)將pdf文件轉(zhuǎn)為圖片,用于頁(yè)面展示問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07concent漸進(jìn)式重構(gòu)react應(yīng)用使用詳解
這篇文章主要為大家介紹了concent漸進(jìn)式重構(gòu)react應(yīng)用的使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11React?Hooks項(xiàng)目實(shí)戰(zhàn)
React?Hooks是React?16.8版本引入的新特性,它使得在函數(shù)組件中也能夠使用狀態(tài)(state)和其他React特性,本文就來(lái)詳細(xì)介紹一下React?Hooks項(xiàng)目實(shí)戰(zhàn),感興趣的可以了解一下2023-11-11React中的useState如何改變值不重新渲染的問(wèn)題
這篇文章主要介紹了React中的useState如何改變值不重新渲染的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03react-navigation 如何判斷用戶(hù)是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法
本篇文章主要介紹了react-navigation 如何判斷用戶(hù)是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12