Next.js と TypeScript で、Reactのイベント処理を学ぶ

TwitterFacebookHatena

TL;DR

このページでは、Next.js と TypeScript を使用した React イベントの実装方法について解説します。その過程で、イベントが React と一緒にどのように機能するのか、そしてそれらを TypeScript で型付けする際の考え方を調べてみましょう。

開発環境 バージョン
Next.js 13.4.4
TypeScript 5.0.4
Emotion 11.11.0
React 18.2.0

イベントとは?

React のイベントシステムの前に、「イベント」について解説します。

イベントとは、あなたが何かを行うことで、コンピュータやプログラムが反応するための「トリガー(引き金)」のようなものです。例えば、ボタンをクリックしたり、キーボードのキーを押したり、マウスを動かしたりすると、それらはすべて「イベント」と呼ばれます。

それでは、このイベントを楽しい例え話で考えてみましょう。あなたが公園で遊んでいて、フリスビーを投げるとします。あなたがフリスビーを投げる行為は「イベント」です。そして、あなたの友達(ここではコンピュータやプログラムと考えてみてください)がそれを見て、フリスビーを追いかけるという反応を起こします。

ここで、フリスビーを投げる行為が「イベント」であり、フリスビーを追いかける行為が「イベントハンドラ(イベント処理)」となります。フリスビーを投げたときに何が起こるのか(友達がフリスビーを追いかける)は、事前に決めておくことができます。これがプログラミングにおける「イベントハンドリング」の基本的な考え方です。

なので、例えばボタンをクリックしたら、何か特定の動作をするようにプログラミングすることができます。この特定の動作が「イベントハンドラ」で、それをプログラムすることを「イベントハンドリング」と呼びます。

React イベントシステムとは?

React のイベントシステムは、ブラウザの標準イベントシステムを抽象化したもので、各種ブラウザのイベントの違いを吸収し、一貫したイベントハンドリングの体験を提供します。JavaScript のイベントリスナーとは違い、React のイベントはキャメルケースで書かれ、JSX に直接渡されます。

React では様々な種類のイベントに対応しています。以下の表はその一部です。

イベント種別 用途
クリックイベント onClick ボタンやリンクのクリック、要素上でのマウスダウン&アップイベントに対応
フォームイベント onChange, onSubmit 入力値の変更、フォームの送信に対応
キーボードイベント onKeyDown, onKeyUp キーボードのキー押下、キー解放に対応
マウスイベント onMouseOver, onMouseOut マウスカーソルの要素上への入出に対応
フォーカスイベント onFocus, onBlur 要素のフォーカス取得、フォーカス失いに対応
スクロールイベント onScroll スクロール操作に対応
タッチイベント onTouchStart, onTouchEnd タッチデバイス(スマートフォンやタブレット)のタッチ開始、タッチ終了に対応
ドラッグ&ドロップイベント onDrag, onDrop ドラッグ操作、ドロップ(ドラッグ中の要素の放下)に対応

これらのイベントハンドラは、関数を受け取り、その関数内でイベントに対する動作を定義します。イベントハンドラは、通常、React のコンポーネントの中で定義されます。

基本的な onClick イベントのハンドラは以下のようになります。

type Props = {
  text: string
}

const ButtonComponent = ({ text }: Props) => {
  const handleClick = () => {
    console.log('Button clicked!')
  }

  return <button onClick={handleClick}>{text}</button>
}

このソースコードでは、ButtonComponentというボタンコンポーネントを作成しています。handleClick関数は、ボタンがクリックされたときにコンソールにメッセージを表示します。

Next.js で、React イベントを実装

Next.js での React イベントの取り扱いは、通常の React アプリと同じです。それでは、より具体的な例を見てみましょう。

次のソースコードは、テキストフィールドからユーザーの入力を受け取り、onChange イベントを使って入力を state で管理するコンポーネントです。

// components/InputField.tsx
import { useState } from 'react'

type Props = {
  placeholder: string
}

const InputField = ({ placeholder }: Props) => {
  const [value, setValue] = useState('')

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setValue(e.target.value)
  }

  return <input type="text" placeholder={placeholder} value={value} onChange={handleChange} />
}

export default InputField

上記のコードでは、useStateフックを使ってユーザーの入力を追跡します。handleChange関数では、イベントオブジェクト e を受け取り、その value プロパティを setValue に渡して state を更新しています。

高度なイベント処理

React のイベント処理の考え方を更に広げてみましょう。例えば、複数の input フィールドの値を一度に管理するためのハンドラを作成します。

// components/MultiInputField.tsx
import { useState } from 'react'

type FormData = {
  firstName: string
  lastName: string
}

const MultiInputField = () => {
  const initialFormData: FormData = {
    firstName: '',
    lastName: '',
  }

  const [formData, setFormData] = useState(initialFormData)

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setFormData({
      ...formData,
      [e.target.name]: e.target.value,
    })
  }

  return (
    <>
      <input type="text" name="firstName" value={formData.firstName} onChange={handleChange} />
      <input type="text" name="lastName" value={formData.lastName} onChange={handleChange} />
    </>
  )
}

export default MultiInputField

ここでは、複数の入力フィールド(名前と姓)の値を一つの state オブジェクトで管理します。各入力フィールドは固有の name 属性を持ち、この name 属性は handleChange 関数内で利用されています。

Emotion での実装

Emotion は、CSS-in-JS ライブラリの一つで、React コンポーネント内で CSS を直接記述することができます。それでは、Emotion を使ってスタイル付きのボタンを作成し、そのボタンがクリックされたときに特定のアクションを実行するような例を見てみましょう。

// components/StyledButton.tsx
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'

type Props = {
  text: string
}

const buttonStyles = css`
  padding: 10px 20px;
  background-color: #0070f3;
  border: none;
  color: #fff;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 0.2s ease;

  &:hover {
    background-color: #0051bb;
  }
`

const StyledButton = ({ text }: Props) => {
  const handleClick = () => {
    console.log('Styled button clicked!')
  }

  return (
    <button css={buttonStyles} onClick={handleClick}>
      {text}
    </button>
  )
}

export default StyledButton

ここでは、ボタンのスタイルを buttonStyles という定数に定義し、それをボタンコンポーネントに適用します。そして、ボタンがクリックされたときに handleClick 関数が呼び出され、コンソールにメッセージが出力されます。

以上が、Next.js と TypeScript で React のイベント処理を実装する方法についてのガイドでした。これらの概念を理解して使いこなすことで、よりリッチでインタラクティブなユーザーインターフェースを構築することができます。

Next.js と TypeScript で、Reactのイベント処理を学ぶ