React でユーザーイベントを TypeScript で管理する

Juan Diego Rodriguez 2023年12月11日
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;

そして、MessageGame から 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 では、これによってエラーが発生することはありませんが、MessageonClicktext の小道具には暗黙的に 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 を使用して ButtonHTMLAttributesonClick プロパティを割り当てます。

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 Rodriguez avatar Juan Diego Rodriguez avatar

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