使用 TypeScript 管理 React 中的使用者事件
本教程將展示如何在 React 中使用 TypeScript 管理使用者的事件,方法是在使用者的操作上從一個元件到另一個元件傳遞一個 onClick
函式。
使用 TypeScript 在 React 中管理使用者事件
我們將使用 create-react-app
快速啟動和執行一個新的 React 專案。
npx create-react-app my-app --template typescript
cd my-app
npm run start
安裝必要的包並啟動開發伺服器後,我們將轉到 src/App.tsx
,刪除所有樣板程式碼並留下一個空元件。
import React from "react";
function Message() {
return <div></div>;
}
export default Message;
現在我們將在 div
新增一個使用者可以單擊的按鈕,我們將通過在 onClick
屬性中傳遞一個帶有警報的函式來響應。
function Message() {
return (
<div>
<button
onClick={() => {
alert("I was clicked!");
}}>
Click Me!
</button>
</div>
);
}
從 Vanilla React 到 TypeScript 沒有任何變化,但是一旦我們希望將 onClick
函式作為 Message
元件的 prop 傳遞,情況就不同了。為了展示這一點,我們將建立另一個名為 Game
的元件,它將 Message
作為其子元件。
function Game() {
return (
<div>
<Message></Message>
</div>
);
}
export default Game;
我們將使 Message
接收它的 onClick
功能和 text
作為來自 Game
的道具。
function Message({onClick, text}) {
return (
<div>
<button onClick={onClick}>{text}</button>
</div>
);
}
function Game() {
return (
<div>
<Message
onClick={() => {
alert("I was clicked!");
}}
text="Click me!"></Message>
</div>
);
}
但是,如果我們執行此程式碼,我們將得到以下編譯錯誤。
Binding element 'onClick' implicitly has an 'any' type.
Binding element 'text' implicitly has an 'any' type.
在 Vanilla JavaScript 中,這不會導致錯誤,但 TypeScript 會丟擲錯誤,因為 Message
的 onClick
和 text
道具隱含地具有 any
型別,即我們沒有宣告這些道具應該是哪種型別店鋪。我們必須建立一個介面來指定 Message
的道具應該具有哪種型別來解決這個問題。
interface MessageProps {
text: string;
onClick: {};
}
text
屬性應該具有的值很容易宣告,因為它只是一個字串。但是 onClick
的值更難。
onClick
不僅僅是一個常規函式,因為它具有 event
屬性,並且它是 button
元素的預定屬性。因此,要定義 onClick
,我們需要一個 React 附帶的預定義介面,在本例中稱為 ButtonHTMLAttributes
,它包含來自 button
元素的所有屬性型別。
要使用它,我們必須擴充套件MessageProps
介面來儲存 ButtonHTMLAttributes
型別。
interface MessageProps extends ButtonHTMLAttributes {
text: string;
}
然而,這還不夠,執行這樣的程式碼會丟擲一個錯誤,因為 ButtonHTMLAttributes
介面是一個 Generic Type。你可以將泛型型別視為帶有變數的介面,為了使用它們,我們在宣告介面後將它們包裹在 <>
周圍。
在這種情況下,ButtonHTMLAttributes
介面需要一個變數來知道我們正在使用哪個 HTML 元素,它將是全域性的 HTMLButtonElement。
interface MessageProps extends ButtonHTMLAttributes<HTMLButtonElement> {
text: string;
}
MessageProps
不僅包含 text
和 onClick
道具的型別,還包含 button
元素的所有道具的型別。你可以將 button
中的任何道具新增到 Message
。
如果你只想擴充套件 onClick
屬性,不要擴充套件介面,建立一個新的 onClick
型別並使用索引訪問型別分配 ButtonHTMLAttributes
的 onClick
屬性。
interface MessageProps {
text: string;
onClick: ButtonHTMLAttributes<HTMLButtonElement>["onClick"];
}
最後,我們必須宣告 Message
元件將通過以下方式將 MessageProps
用於其 props。
function Message({onClick, text}: MessageProps) {
return (
<div>
<button onClick={onClick}>{text}</button>
</div>
);
}
如果我們願意,我們可以將返回型別註釋為 JSX.Element
,這樣如果我們不小心返回了其他型別,TypeScript 就會丟擲錯誤。
function Message({onClick, text}: MessageProps): JSX.Element {
return (
<div>
<button onClick={onClick}>{text}</button>
</div>
);
}
這將是最終的結果。
import React from "react";
import {ButtonHTMLAttributes} from "react";
interface MessageProps {
text: string;
onClick: ButtonHTMLAttributes<HTMLButtonElement>["onClick"];
}
function Message({onClick, text}: MessageProps): JSX.Element {
return (
<div>
<button onClick={onClick}>{text}</button>
</div>
);
}
function Game() {
return (
<div>
<Message
onClick={() => {
alert("I was clicked!");
}}
text="Click me!"></Message>
</div>
);
}
export default Game;
Juan Diego Rodríguez (also known as Monknow) is a front-end developer from Venezuela who loves to stay updated with the latest web development trends, making beautiful websites with modern technologies. But also enjoys old-school development and likes building layouts with vanilla HTML and CSS to relax.
LinkedIn