React高階組件詳解:使用 TypeScript 實(shí)現(xiàn)日志記錄組件

閱讀時(shí)間約為:6 分鐘。

本文首發(fā)于個(gè)人博客:React高階組件詳解:使用 TypeScript 實(shí)現(xiàn)日志記錄組件涩盾。


我們知道 React 是一個(gè)用于構(gòu)建用戶界面的 JavaScript 庫(kù)十气,其中,React 組件是 React 應(yīng)用程序的核心春霍,它們用于組合并呈現(xiàn)應(yīng)用程序的不同部分砸西。有時(shí),我們需要增強(qiáng)組件的功能址儒,但又不希望修改原始組件的代碼芹枷。這時(shí),React 高階組件(Higher-Order Components莲趣,HOC)就派上用場(chǎng)了鸳慈。

React 高階組件是一個(gè)非常強(qiáng)大的工具,可以幫助我們?cè)诓恍薷默F(xiàn)有組件的情況下增強(qiáng)組件功能妖爷。在本文中蝶涩,我們將使用 TypeScript 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的日志記錄高階組件示例理朋,并解釋如何編寫和使用高階組件。以演示如何使用高階組件來增強(qiáng)組件功能绿聘,而不需要修改原始組件的代碼嗽上。

什么是高階組件

高階組件是一個(gè)函數(shù),它接收一個(gè)組件作為參數(shù)熄攘,并返回一個(gè)新的組件兽愤。新組件包裝了原始組件,并增強(qiáng)了它的功能挪圾。高階組件可以用于添加共同的邏輯或功能到多個(gè)組件中浅萧,這種方法在很多情況下比繼承或組件復(fù)用更靈活。

在 React 中哲思,高階組件通常被用于以下場(chǎng)景:

  • 代碼復(fù)用:將共同的邏輯提取到高階組件中洼畅,以便在多個(gè)組件中重復(fù)使用。
  • 功能增強(qiáng):高階組件可以通過添加或修改 props棚赔、渲染邏輯或生命周期方法來增強(qiáng)組件的功能帝簇。
  • 渲染劫持:高階組件可以通過更改組件的渲染行為來修改組件的外觀或行為。

實(shí)現(xiàn)一個(gè)日志記錄高階組件

在本文中靠益,我們將使用 TypeScript 和 React 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的日志記錄高階組件丧肴,以演示高階組件的使用方法。

首先胧后,我們定義一個(gè)高階組件函數(shù) withLogging 芋浮,它接收一個(gè)泛型參數(shù) P ,表示原始組件的 props 類型壳快。該函數(shù)返回一個(gè)新的函數(shù)組件 WithLogging 纸巷,這個(gè)組件可以包裝原始組件并添加日志信息。


import React, { FC } from 'react';

// 高階函數(shù)接收一個(gè)泛型參數(shù) P眶痰,表示原始組件的 props 類型
interface WithLoggingProps {
  name: string;
}

const withLogging = <P extends object>(WrappedComponent: React.ComponentType<P>) => {
  // 返回一個(gè)新的函數(shù)組件何暇,這個(gè)組件可以包裝原始組件
  const WithLogging: FC<P & WithLoggingProps> = (props) => {
    // 在渲染時(shí)添加日志信息
    console.log(`Rendering component: ${WrappedComponent.displayName || WrappedComponent.name}`);
    return <WrappedComponent {...props as P} />;
  };
  // 設(shè)置新組件的 displayName,便于調(diào)試
  WithLogging.displayName = `WithLogging(${WrappedComponent.displayName || WrappedComponent.name})`;
  return WithLogging;
};

withLogging 函數(shù)內(nèi)部凛驮,我們創(chuàng)建一個(gè)名為 WithLogging 的新函數(shù)組件。這個(gè)組件會(huì)接收原始組件的 props 和一個(gè)名為 name 的字符串參數(shù)条辟。在渲染時(shí)黔夭,它會(huì)打印一個(gè)帶有組件名稱的日志消息,并渲染原始組件羽嫡。我們還設(shè)置了新組件的 displayName本姥,以便更好地調(diào)試。

現(xiàn)在杭棵,我們可以使用 withLogging 高階組件來包裝一個(gè)原始組件婚惫,并增強(qiáng)它的功能氛赐。例如,我們可以創(chuàng)建一個(gè)簡(jiǎn)單的無狀態(tài)組件 Button 先舷,它只是渲染了一個(gè)按鈕艰管。

// 一個(gè)簡(jiǎn)單的無狀態(tài)組件
const Button: FC = () => {
  return <button>Click me</button>;
};

現(xiàn)在,我們可以像使用 Button 一樣使用 LoggedButton 組件蒋川,但是它會(huì)在每次渲染后被點(diǎn)擊時(shí)打印一個(gè)日志消息牲芋。

// 使用高階組件包裝 Button 組件
const ButtonWithLogging = withLogging(Button);

// 渲染應(yīng)用程序組件
export default function App() {
  return (
    <div>
      {/* 使用包裝后的 Button 組件 */}
      <ButtonWithLogging name="Submit" />
    </div>
  );
}

使用 withLogging 高階組件,我們可以輕松地添加日志記錄和其他功能到多個(gè)組件中捺球,而不需要修改這些組件的代碼缸浦。這使得代碼更容易維護(hù),更具可讀性氮兵。

在瀏覽器中執(zhí)行上面的例子裂逐,會(huì)渲染一個(gè)包含一個(gè)按鈕的頁(yè)面,并在每次點(diǎn)擊按鈕時(shí)泣栈,在瀏覽器的控制臺(tái)中打印一條日志信息卜高。這是由于 withLogging 高階組件包裝了 Button 組件,并添加了一個(gè)事件監(jiān)聽器秩霍,在每次點(diǎn)擊按鈕時(shí)記錄一條日志篙悯。

假設(shè)這個(gè)按鈕被點(diǎn)擊了 5 次,輸出到瀏覽器控制臺(tái)的結(jié)果應(yīng)該是類似下面這樣的內(nèi)容:

Rendering component: WithLogging(Button)
Rendering component: WithLogging(Button)
Rendering component: WithLogging(Button)
Rendering component: WithLogging(Button)
Rendering component: WithLogging(Button)

總結(jié)

React 高階組件是一個(gè)非常強(qiáng)大的工具铃绒,可以幫助我們?cè)诓恍薷默F(xiàn)有組件的情況下增強(qiáng)組件功能鸽照。在本文中,我們使用 TypeScript 和 React 實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的日志記錄高階組件颠悬,并解釋了如何編寫和使用高階組件矮燎。通過使用高階組件,我們可以輕松地添加共同的邏輯或功能到多個(gè)組件中赔癌,使得代碼更容易維護(hù)和重用诞外。


喜歡的話,就來微信公眾號(hào)“若非的日志”一起學(xué)習(xí)啊~
微信公眾號(hào):若非的日志原創(chuàng)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灾票,一起剝皮案震驚了整個(gè)濱河市峡谊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌刊苍,老刑警劉巖既们,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異正什,居然都是意外死亡啥纸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門婴氮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斯棒,“玉大人盾致,你說我怎么就攤上這事∪倌海” “怎么了庭惜?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)渠驼。 經(jīng)常有香客問我蜈块,道長(zhǎng),這世上最難降的妖魔是什么迷扇? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任百揭,我火速辦了婚禮,結(jié)果婚禮上蜓席,老公的妹妹穿的比我還像新娘器一。我一直安慰自己,他們只是感情好厨内,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布祈秕。 她就那樣靜靜地躺著,像睡著了一般雏胃。 火紅的嫁衣襯著肌膚如雪请毛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天瞭亮,我揣著相機(jī)與錄音方仿,去河邊找鬼。 笑死统翩,一個(gè)胖子當(dāng)著我的面吹牛仙蚜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播厂汗,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼委粉,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了娶桦?” 一聲冷哼從身側(cè)響起贾节,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衷畦,沒想到半個(gè)月后氮双,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霎匈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了送爸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铛嘱。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡暖释,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出墨吓,到底是詐尸還是另有隱情球匕,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布帖烘,位于F島的核電站亮曹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秘症。R本人自食惡果不足惜照卦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乡摹。 院中可真熱鬧役耕,春花似錦、人聲如沸聪廉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)板熊。三九已至框全,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間干签,已是汗流浹背津辩。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留筒严,地道東北人丹泉。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鸭蛙,于是被迫代替她去往敵國(guó)和親摹恨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容