iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0
Modern Web

前進React 生態系 : 技術應用與概念解析系列 第 5

Day 05 - 掌握 ComponentProps:讓 React 元件型別更輕鬆

  • 分享至 

  • xImage
  •  

取得 HTML 元素的 props

在建立共用元件時,有時候會需要繼承到 HTML 元素的 props,這時候就需要針對原本的 props 做修改或擴充。但一個元件有這麼多 props,不可能一個一個來寫,這時候就可以用到 ComponentProps 來取得。

以下是範例,以 Button 元件為例:

import { ComponentProps } from "react";

type ButtonProps = ComponentProps<"button"> & {
  icon?: React.ReactNode;
  text: string;
};

export default function Button({ icon, text, ...props }: ButtonProps) {
  return (
    <button
      className="flex items-center space-x-2 px-4 py-2 bg-blue-500 text-white rounded-md"
      {...props}
    >
      {icon && <span>{icon}</span>}
      <span>{text}</span>
    </button>
  );
}

這邊透過 ComponentProps 來取得 button 元素的所有 props 並加以擴充,增加自訂的 icontext 屬性。

如果想要更明確的知道 props 是否包含 ref,也可以改用 ComponentPropsWithRefComponentPropsWithoutRef

使用第三方套件

在 React 開發時常會使用到第三方套件,大部分都有 @types/ 套件來提供型別。但有時候並不是所有套件都會有提供,或是提供的型別文件不清楚。如果使用的元件沒有型別的話,也可以用 ComponentProps 來取得。

import { ComponentProps } from "react";
import { Button } from "some-external-library";

type MyButtonProps = ComponentProps<typeof Button>;

這樣我們就可以在自己的 Button 元件中擴展第三方元件的 props。

取得 React 事件的型別

在使用 TypeScript 開發時,另一個常見需求是取得事件的型別。但通常事件型別名稱很長,難以記住。
不知道event型別

有幾種簡單的方法可以取得這些事件型別:

方法 1: Hover 取得事件型別

將滑鼠懸停在事件的名稱上,TypeScript 會自動顯示該事件的型別。以下是 hover 到 onClick 事件後所顯示的結果:
hover到onClick

雖然這是個快速方法,但複製起來貼上還是有點麻煩。

方法 2: React ComponentProps

import { ComponentProps } from "react";

const handleClick: ComponentProps<"button">["onClick"] = (e) => {
  //...
};

簡單又好記。

另外現在 AI 工具也很聰明,也會自動建議相關型別 (當然還是要檢查一下)。

參考資料:
https://www.totaltypescript.com/concepts/react-componentprops-type-helper
https://www.totaltypescript.com/react-component-props-type-helper
https://twitter.com/sebastienlorber/status/1512420374201446405


上一篇
Day 04 - 掌握 TypeScript Discriminated Unions:提升 React 組件的靈活性與安全性
下一篇
Day 06 - TypeScript 語法技巧與 Zod 簡介
系列文
前進React 生態系 : 技術應用與概念解析30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言