日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

React + TypeScript 实现泛型组件

發布時間:2024/8/26 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 React + TypeScript 实现泛型组件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

泛型類型

TypeScript 中,類型(interface, type)是可以聲明成泛型的,這很常見。

interface Props<T> {content: T; }

這表明 Props 接口定義了這么一種類型:

  • 它是包含一個 content 字段的對象
  • 該 content 字段的類型由使用時的泛型 T 決定
type StringProps = Props<string>;let props: StringProps;props = {// ? Type 'number' is not assignable to type 'string'.ts(2322)content: 42 };props = {// ?content: "hello" };

或者,TypeScript 能夠跟使用時候提供的值自動推斷出類型 T,無需顯式指定:

interface Props<T> {content: T; }function Foo<T>(props: Props<T>) {console.log(props); }/** 此時 Foo 的完整簽名為: function Foo<number>(props: Props<number>): void */ Foo({ content: 42 });/** 此時 Foo 的完整簽名為: function Foo<string>(props: Props<string>): void */ Foo({ content: "hello" });

上面因為 Foo 函數接收 Props<T> 作為入參,意味著我們在調用 Foo 的時候需要傳遞類型 T 以確定 Props<T>,所以 Foo 函數也變成了泛型。

當調用 Foo({ content: 42 }) 的時候,TypeScript 自動解析出 T 為 number,此時對應的函數簽名為:

function Foo<number>(props: Props<number>): void;

而我們并沒有顯式地指定其中的類型 T,像這樣 Foo<number>({ content: 42 });。

泛型組件

將上面的 Foo 函數返回 JSX 元素,就成了一個 React 組件。因為它是泛型函數,它所形成的組件也就成了 泛型組件/Generic Components

function Foo<T>(props: Props<T>) {return <div> {props.content}</div>; }const App = () => {return (<div className="App"><Foo content={42}></Foo><Foo<string> content={"hello"}></Foo></div>); };

一如上面的討論,因為 TypeScript 可根據傳入的實際值解析泛型類型,所以 <Foo<string> content={"hello"}></Foo> 中 string 是可選的,這里只為展示,讓你看到其實 React 組件還可以這么玩。

為了進一步理解泛型組件,再看下非泛型情況下上面的組件是長怎樣的。

interface Props {content: string; }function Foo(props: Props) {return <div>{props.content}</div>; }const App = () => {return (<div className="App">{/* ? Type 'number' is not assignable to type 'string'.ts(2322) */}<Foo content={42}></Foo><Foo content={"hello"}></Foo></div>); };

以上,便是一個 React 組件常規的寫法。它定義的入參 Props 只接收 string 類型。由此也看出泛型的優勢,即大部分代碼可復用的情況下,將參數變成泛型后,不同類型的入參可復用同一組件,不用為新類型新寫一個組件。

除了函數組件,對于類類型的組件來說,也是一樣可泛型化的。

interface Props<T> {content: T; }class Bar<T> extends React.Component<Props<T>> {render() {return <div>{this.props.content}</div>;} }const App = () => {return (<div className="App"><Bar content={42}></Bar><Bar<string> content={"hello"}></Bar></div>); };

一個更加真實的示例

一個更加實用的示例是列表組件。列表中的分頁加載,滾動刷新邏輯等,對于所有列表數據都是通用的,將這個列表組件書寫成泛型便可和任意類型列表數據結合,而無須通過其他方式來達到復用的目的,將列表元素聲明成 any 或 Record<string,any> 等類型。

先看不使用泛型情況下,如何實現這么一個列表組件。此處只看列表元素的展示以闡述泛型的作用,其他邏輯比如數據加載等先忽略。

列表組件 List.tsx

interface Item {[prop: string]: any; }interface Props {list: Item[];children: (item: Item, index: number) => React.ReactNode; }function List({ list, children }: Props) {// 列表中其他邏輯...return <div>{list.map(children)}</div>; }

上面,為了盡可能滿足大部分數據類型,將列表的元素類型定義成了 [prop: string]: any; 的形式,其實和 Record<string,any> 沒差。在這里已經可以看到類型的丟失了,因為出現了 any,而我們使用 TypeScript 的首要準則是盡量避免 any。

然后是使用上面所定義的列表組件:

interface User {id: number;name: string; } const data: User[] = [{id: 1,name: "wayou"},{id: 1,name: "niuwayong"} ];const App = () => {return (<div className="App"><List list={data}>{item => {// ? 此處 `item.name` 類型為 `any`return <div key={item.name}>{item.name}</div>;}}</List></div>); };

這里使用時,item.name 的類型已經成了 any。對于簡單數據來說,還可以接收這樣類型的丟失,但對于復雜類型,類型的丟失就完全享受不到 TypeScript 所帶來的類型便利了。

上面的實現還有個問題是它規定了列表元素必需是對象,理所應當地就不能處理元始類型數組了,比如無法渲染 ['wayou','niuwayong'] 這樣的輸入。

下面使用泛型改造上面的列表組件,讓它支持外部傳入類型。

interface Props<T> {list: T[];children: (item: T, index: number) => React.ReactNode; }function List<T>({ list, children }: Props<T>) {// 列表中其他邏輯...return <div>{list.map(children)}</div>; }

改造后,列表元素的類型完全由使用的地方決定,作為列表組件,內部它無須關心,同時對于外部傳遞的 children 回調中 item 入參,類型也沒有丟失。

使用改造后的泛型列表:

interface User {id: number;name: string; } const data: User[] = [{id: 1,name: "wayou"},{id: 1,name: "niuwayong"} ];const App = () => {return (<div className="App"><List list={data}>{item => {// ? 此處 `item` 類型為 `User`return <div key={item.name}>{item.name}</div>;}}</List><List list={["wayou", "niuwayong"]}>{item => {// ? 此處 `item` 類型為 `string`return <div key={item}>{item}</div>;}}</List></div>); };

轉載于:https://www.cnblogs.com/Wayou/p/react_typescript_generic_components.html

總結

以上是生活随笔為你收集整理的React + TypeScript 实现泛型组件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。