💡

buttonとaタグの両方に対応するonClickイベント

2024/06/19に公開

はじめに

Reactでボタンやリンクのクリックイベントを処理する際、buttonタグとaタグではイベントの型が異なるため、同じonClickハンドラを使用することが難しくなります。この問題を解決し、両方のタグに対応する汎用的なonClickハンドラを実装する方法について解説します。

問題

通常、buttonタグとaタグの両方に対応するコンポーネントを作成する際、onClickイベントの型の違いにより、型エラーが発生します。HTMLButtonElementとHTMLAnchorElementのイベント型が異なるため、同じonClickハンドラを共有することが困難です。

const onClick = (e: React.MouseEvent<HTMLButtonElement>) => {
  e.preventDefault();
};

このコードは、HTMLButtonElementに特化した型を使用しているため、HTMLAnchorElementに対しては互換性がありません。

解決方法

イベントのターゲットをHTMLElementとして扱い、buttonとaタグの両方に対応するようにします。

実装例

以下のコードは、buttonとaの両方に対応するButtonコンポーネントの実装例です。

import { PropsWithChildren } from "react";
import Link from "next/link";

type Props = PropsWithChildren<{
  href?: string;
  onClick: (e: React.MouseEvent<HTMLElement>) => void;
}>;

export const Button = ({ href, onClick, children }: Props) => {
  if (href) {
    return (
      <Link href={href} onClick={onClick}>
        {children}
      </Link>
    );
  }

  return <button onClick={onClick}>{children}</button>;
};

おわりに

この方法を用いることで、buttonとaの両方に対応する汎用的なonClickイベントハンドラを実装することができます。

Discussion