TL;DR
この記事では、React 関数コンポーネントの基礎について詳しく見ていきますね。一言でいうと、React 関数コンポーネントとは React のコンポーネントを関数で定義する方法です。
開発環境 | バージョン |
---|---|
Next.js | 13.4.4 |
TypeScript | 5.0.4 |
Emotion | 11.11.0 |
React | 18.2.0 |
関数コンポーネントとは?
React.js では、UI の一部分をコンポーネントと呼ばれる単位に分割し、これらを組み合わせることで Web アプリケーションを構築します。そして、そのコンポーネントの定義方法として「関数コンポーネント」があります。関数コンポーネントは、関数として定義されるコンポーネントで、最もシンプルな形式の React コンポーネントです。
const Greeting = () => <h1>こんにちは!</h1>
上記の例は、文字列"こんにちは!"を表示する関数コンポーネント Greeting を定義しています。このように、関数コンポーネントは、状態を持たず、ライフサイクルも持たないシンプルな UI 部品を構築するのに適しています。
ただし、React Hooks の導入により、関数コンポーネントでも状態管理やライフサイクルメソッドに相当する機能を利用することができるようになりました。これにより、クラスコンポーネントと同等の機能を持つ関数コンポーネントを作ることが可能となりました。
Next.js で、関数コンポーネントを実装
それでは、Next.js と TypeScript を用いて、具体的な関数コンポーネントを作ってみましょう。以下に、"Hello, Next.js!"というメッセージを表示する簡単なコンポーネントを作成する方法を示します。
// pages/index.tsx
import type { NextPage } from 'next'
const HomePage: NextPage = () => {
return <h1>Hello, Next.js!</h1>
}
export default HomePage
上記のソースコードは、pages/index.tsx
というファイルに記述され、Next.js のエントリーポイント(アプリケーションの開始点)となるコンポーネントを定義しています。
このHomePage
は、Next.js の固有の型NextPage
を使用しています。これにより、このコンポーネントが Next.js 特有のプロパティ(例えばgetInitialProps
)を持つことが保証されます。また、Next.js はファイルベースのルーティングを提供しており、このpages/index.tsx
ファイルは自動的に/
(ルート)パスにマッピングされます。
return <h1>Hello, Next.js!</h1>;
により、ブラウザに表示される HTML 要素が生成されます。この<h1>
は、React 要素を生成する JSX という構文を用いて記述されています。
関数コンポーネントをさらに理解する
それでは、よりテクニカルな側面を含む関数コンポーネントを見ていきましょう。具体的には、props と状態管理について考えてみます。
props は、コンポーネントの外部から渡されるデータを表し、コンポーネントはこれを受け取ります。これにより、コンポーネントは再利用可能となり、異なるデータを表示することができます。
また、React では「状態」という考え方を導入しており、これはコンポーネント内で変化するデータを扱うためのものです。React Hooks を用いると、関数コンポーネントでも状態を管理することができます。
以下に、props と状態を使った関数コンポーネントの例を示します。
// components/Counter.tsx
import { useState } from 'react'
type CounterProps = {
initialCount: number
}
const Counter = ({ initialCount }: CounterProps) => {
const [count, setCount] = useState(initialCount)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
)
}
export default Counter
このCounter
コンポーネントは、initialCount
という props を受け取り、これを初期値とするカウンターを提供します。そして、ユーザがボタンをクリックするとカウンターが増加します。カウンターの現在の値は、状態として管理され、useState
フックによって設定と更新が行われます。
コンポーネントの作成とインポート
では、先程作成した Counter
コンポーネントを使って、他のコンポーネントからインポートする方法を解説いたします。この Counter
コンポーネントを HomePage
からインポートし、使用する例を見ていきましょう。
まずは、Counter
コンポーネントを HomePage
にインポートするためのコードを示します。その後、そのコードを分解して説明していきます。
// pages/index.tsx
import type { NextPage } from 'next'
import Counter from '../components/Counter'
const HomePage: NextPage = () => {
return (
<div>
<h1>Hello, Next.js!</h1>
<Counter initialCount={0} />
</div>
)
}
export default HomePage
この HomePage
コンポーネントでは、まず初めに Counter
コンポーネントをインポートしています。ここでのパス '../components/Counter'
は、Counter.tsx
ファイルが存在する場所を指しています。
そして、JSX の中で <Counter initialCount={0} />
という形で Counter
コンポーネントを使います。ここで、initialCount={0}
としている部分が props の渡し方を示しています。この例では、initialCount
という名前の props を Counter
コンポーネントに渡し、その初期値を 0
に設定しています。
以上が、関数コンポーネントを作成し、それを他のコンポーネントからインポートする基本的な手順です。この手順を理解し、再利用可能なコンポーネントを作成することで、効率的な開発を行うことができます。
テクニカルな関数コンポーネントの例
では、さらにテクニカルな関数コンポーネントの例として、ユーザーの一覧を表示する UserList
コンポーネントを作成してみましょう。この UserList
コンポーネントでは、props として渡されたユーザーのデータを元に、ユーザーの一覧を描画します。
// components/UserList.tsx
type User = {
id: number
name: string
}
type Props = {
users: User[]
}
const UserList = ({ users }: Props) => {
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)
}
export default UserList
この UserList
コンポーネントでは、User
という型を定義し、その配列である User[]
を props として受け取ります。その後、users.map()
を使って、ユーザー一人一人をリストの項目 <li>
として描画します。この時、key
属性にはユーザーの id
を設定します。React では、配列を元に描画する際に各要素がユニークであることを保証するために key
属性が必要です。
次に、この UserList
コンポーネントを使う HomePage
コンポーネントの例を見てみましょう。
// pages/index.tsx
import type { NextPage } from 'next'
import UserList from '../components/UserList'
const users = [
{ id: 1, name: 'Taro' },
{ id: 2, name: 'Jiro' },
{ id: 3, name: 'Saburo' },
]
const HomePage: NextPage = () => {
return (
<div>
<h1>User List</h1>
<UserList users={users} />
</div>
)
}
export default HomePage
HomePage
コンポーネントでは、先程作成した UserList
コンポーネントをインポートし、users
という名前の props を渡しています。ここで、users
はユーザーのデータの配列です。
以上が、テクニカルな関数コンポーネントの作成と使用の例です。この例を通じて、関数コンポーネントがどのようにデータを受け取り、それを元に描画を行うのか理解できたかと思います。これらの知識を応用して、さまざまなコンポーネントを作成し、再利用性の高いコードを書いていきましょう。