React でユーザーイベントを TypeScript で管理する
このチュートリアルでは、React で TypeScript を使ってユーザーのイベントを管理する方法として、ユーザーのアクションに対してコンポーネントからコンポーネントへ onClick
関数を渡す方法を紹介します。
React で TypeScript を使ってユーザーイベントを管理する
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
コンポーネントの小道具として渡すようにすると、状況は異なります。これを示すために、メッセージ
を子とするゲーム
という別のコンポーネントを作成します。
function Game() {
return (
<div>
<Message></Message>
</div>
);
}
export default Game;
そして、Message
が Game
から onClick
関数と text
を props として受け取るようにします。
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 では、これによってエラーが発生することはありませんが、Message
の onClick
と text
の小道具には暗黙的に any
タイプがあるため、TypeScript はエラーをスローします。つまり、これらの小道具がどのタイプであるかを宣言していません。お店。メッセージ
の小道具がこれを解決するために必要なタイプを指定するインターフェースを作成する必要があります。
interface MessageProps {
text: string;
onClick: {};
}
text
prop が持つべき値は、単なる文字列であるため、簡単に宣言できます。しかし、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
タイプを作成し、IndexedAccessTypes を使用して ButtonHTMLAttributes
の onClick
プロパティを割り当てます。
interface MessageProps {
text: string;
onClick: ButtonHTMLAttributes<HTMLButtonElement>["onClick"];
}
最後に、Message
コンポーネントが次の方法でその小道具に MessageProps
を使用することを宣言する必要があります。
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