JSX

ジェイエスエックス

JSX を分かりやすく

JSX は、JavaScript 内で HTML タグを記述するための構文拡張です。React や Next.js などのフレームワークでよく使われ、コンポーネントの見た目を効果的に記述することができます。JSX は独自のタグ構文を持っており、JavaScript の変数や関数をタグ内で直接扱うことができます。

JSX を使うメリット

  1. 見た目とロジックを同じ場所に記述することができます。これにより、コンポーネントの関心ごとを一元化し、可読性と保守性が向上します。
  2. JavaScript の機能をフル活用できます。例えば、条件付きレンダリングや繰り返し処理などを簡単に実装することができます。
  3. コンパイル時にチェックが行われるため、エラーを事前に検出できます。これにより、開発効率が向上し、バグを減らすことができます。

JSX のルール

JSX のルールは、以下のようになります。

最上位の要素は一つである必要がある: JSX では、一つのコンポーネント内に複数の同階層の要素を直接配置することはできません。代わりに、最上位の要素を一つ用意し、その中に複数の要素を配置する必要があります。最上位の要素として <div><React.Fragment> などがよく使われます。

class は、className と書く: JSX では、HTML の class 属性は className として記述します。これは、JavaScript の予約語と競合しないようにするためです。

<div className="container">Hello, World!</div>

自己閉じタグを使用する: JSX では、通常の HTML と同様に要素を閉じる必要があります。ただし、空要素(例: <img><input> など)の場合は、自己閉じタグを使用して記述します。

<img src="example.jpg" alt="example" />

式を埋め込む場合は {} で囲む: JSX では、JavaScript の式を {} で囲むことで、タグ内に直接埋め込むことができます。これにより、動的な値や条件分岐などを簡単に実現できます。

<div>{variable}</div>
<div>{condition ? "true" : "false"}</div>

複数行にまたがる場合は () で囲む: JSX のコードが複数行にまたがる場合、コードの見た目を整えるために () で囲むことが一般的です。これにより、インデントや改行が正しく認識され、可読性が向上します。

const component = (
  <div>
    <h1>Title</h1>
    <p>Content</p>
  </div>
)

これらのルールを把握し、実践することで、JSX を使ったコンポーネントの記述がより効率的でメンテナブルになります。

JSX を実装

Next.js と TypeScript を使って、シンプルな JSX の例を見ていきましょう。

まず、components フォルダ内に HelloWorld.tsx ファイルを作成し、以下のコードを記述します。

// components/HelloWorld.tsx
type Props = {
  name: string
}

const HelloWorld = ({ name }: Props) => {
  return <div>Hello, {name}!</div>
}

export default HelloWorld

このコンポーネントは、name というプロパティを受け取り、Hello, {name}! というメッセージを表示します。

次に、pages フォルダ内に index.tsx ファイルを作成し、以下のコードを記述します。

// pages/index.tsx
import { NextPage } from 'next'
import HelloWorld from '../components/HelloWorld'

const IndexPage: NextPage = () => {
  return (
    <div>
      <HelloWorld name="Next.js and TypeScript" />
    </div>
  )
}

export default IndexPage

このページは、先ほど作成した HelloWorld コンポーネントをインポートして使用しています。name プロパパティには "Next.js and TypeScript" という文字列が渡されています。これにより、ブラウザで表示されるメッセージは "Hello, Next.js and TypeScript!" となります。

条件付きレンダリング

JSX を使った条件付きレンダリングの例を見ていきましょう。以下のコードは、isEven プロパティが真の場合に "Even" と表示し、偽の場合に "Odd" と表示するコンポーネントです。

// components/EvenOdd.tsx
type Props = {
  isEven: boolean
}

const EvenOdd = ({ isEven }: Props) => {
  return <div>{isEven ? 'Even' : 'Odd'}</div>
}

export default EvenOdd

pages/index.tsxEvenOdd コンポーネントをインポートし、使用してみましょう。

// pages/index.tsx
import { NextPage } from 'next'
import HelloWorld from '../components/HelloWorld'
import EvenOdd from '../components/EvenOdd'

const IndexPage: NextPage = () => {
  const number = 3

  return (
    <div>
      <HelloWorld name="Next.js and TypeScript" />
      <EvenOdd isEven={number % 2 === 0} />
    </div>
  )
}

export default IndexPage

ここでは、number 変数に 3 を代入し、EvenOdd コンポーネントの isEven プロパティに number % 2 === 0 を渡しています。この結果、ブラウザで表示されるメッセージは "Odd" となります。

繰り返し処理

JSX を使った繰り返し処理の例を見ていきましょう。以下のコードは、items プロパティで受け取った配列を繰り返し処理し、リストとして表示するコンポーネントです。

// components/ItemList.tsx
type Props = {
  items: string[]
}

const ItemList = ({ items }: Props) => {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  )
}

export default ItemList

pages/index.tsxItemList コンポーネントをインポートし、使用してみましょう。

// pages/index.tsx
import { NextPage } from 'next'
import HelloWorld from '../components/HelloWorld'
import EvenOdd from '../components/EvenOdd'
import ItemList from '../components/ItemList'

const IndexPage: NextPage = () => {
  const fruits = ['Apple', 'Banana', 'Cherry']

  return (
    <div>
      <HelloWorld name="Next.js and TypeScript" />
      <EvenOdd isEven={3 % 2 === 0} />
      <ItemList items={fruits} />
    </div>
  )
}

export default IndexPage

ここでは、fruits 配列に果物の名前が格納されており、ItemList コンポーネントの items プロパティに渡しています。これにより、ブラウザ上に以下のようなリストが表示されます。

- Apple
- Banana
- Cherry

このように、JSX を用いることで、条件付きレンダリングや繰り返し処理などの動的な要素を簡潔に記述することができます。また、Next.js と TypeScript を組み合わせることで、型安全性を確保しながら効率的な開発が可能になります。

イベントハンドリング

最後に、JSX を使ったイベントハンドリングの例を見ていきましょう。以下のコードは、ボタンをクリックするとアラートが表示されるコンポーネントです。

// components/AlertButton.tsx
type Props = {
  message: string
}

const AlertButton = ({ message }: Props) => {
  const handleClick = () => {
    alert(message)
  }

  return <button onClick={handleClick}>Click me!</button>
}

export default AlertButton

pages/index.tsxAlertButton コンポーネントをインポートし、使用してみましょう。

// pages/index.tsx
import { NextPage } from 'next'
import HelloWorld from '../components/HelloWorld'
import EvenOdd from '../components/EvenOdd'
import ItemList from '../components/ItemList'
import AlertButton from '../components/AlertButton'

const IndexPage: NextPage = () => {
  const fruits = ['Apple', 'Banana', 'Cherry']

  return (
    <div>
      <HelloWorld name="Next.js and TypeScript" />
      <EvenOdd isEven={3 % 2 === 0} />
      <ItemList items={fruits} />
      <AlertButton message="You clicked the button!" />
    </div>
  )
}

export default IndexPage

ここでは、AlertButton コンポーネントの message プロパティに "You clicked the button!" という文字列を渡しています。ブラウザ上でボタンをクリックすると、アラートが表示され、指定されたメッセージが表示されます。

このように、JSX を使用してイベントハンドリングを簡単に実装することができます。また、Next.js と TypeScript の組み合わせにより、開発効率と信頼性が向上します。

ここまでの例では、Next.js と TypeScript を用いて、JSX の基本的な使い方や実装方法について説明しました。これらの知識を活用して、より効率的で信頼性の高いアプリケーション開発を進めてください。