Reactは、モダンなWebアプリケーション開発において、特にフロントエンド開発で人気のあるJavaScriptライブラリです。その中心的な概念はコンポーネントです。Reactを使うと、再利用可能なコンポーネントを組み合わせてWebアプリケーションを構築することができます。本記事では、Reactのコンポーネントの基本について解説します。
[目次を開く]
1. コンポーネントとは?
コンポーネントは、アプリケーションのUI(ユーザーインターフェース)を分割した再利用可能な部品です。Reactでは、1つのアプリケーションを複数のコンポーネントに分割して、それぞれのコンポーネントが特定の部分を担当する形で構築します。コンポーネントは、以下のように関数やクラスとして定義します。
例:関数コンポーネント
Greeting.tsxを作成してみましょう。
function Greeting() {
return <h1>Hello, React!</h1>;
}
export default Greeting;
上記のコードは、シンプルな関数コンポーネントです。関数コンポーネントは、関数として定義され、React要素を返します。<h1>
要素が返されているため、このコンポーネントを使うと「Hello, React!」というテキストが表示されます。
main.tsxで呼び出してみましょう。
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import Greeting from './Greeting.tsx'
import './index.css'
createRoot(document.getElementById('root')).render(
<StrictMode>
<Greeting />
</StrictMode>,
)
npm run dev
で確認すると、以下のような画面が表示されるはずです。

これで作成した関数コンポーネントをmain.tsxで呼び出すことに成功しました。
上記で関数コンポーネントについて解説しましたが、Reactには、クラスコンポーネントも存在しますが、こちらは現状では目にする機会が少ないです。その理由の1つとしては、関数コンポーネント + Hooks と比べて、記述量が多くなりやすいからです。目にする機会が少ないとはいえ既存のプロジェクトに参画した場合に目にすることもあるかも知れないので、基本的な構文についてはおさえておきましょう。
例:クラスコンポーネント
基本構文
import React, { Component } from 'react';
class Hello extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
上記のコードは、 Hello
コンポーネントが「props.name
を受け取って表示する」っていう単純な構成です。関数で書くときは props
を直接受け取って使いますが、Classの場合は this.props
でアクセスします。
2. JSXとは?
Reactでは、UIを記述するためにJSX(JavaScript XML)という特別な構文が使われます。JSXは、HTMLに似た構文で、JavaScriptの中に埋め込むことができます。JSXを使うことで、直感的にUIを構築することが可能です。
JSXの例
const element = <h1>Hello, world!</h1>;
JSXは通常のHTMLのように見えますが、実際にはJavaScriptの中で扱われるため、JavaScriptの式や変数を簡単に組み込むことができます。
const name = "John";
const element = <h1>Hello, {name}!</h1>; // "Hello, John!" と表示
3. Props(プロパティ)を使ったデータの受け渡し
コンポーネント間でデータを受け渡すためには、props(プロパティ)を使用します。props
は、親コンポーネントから子コンポーネントにデータを渡すための手段です。関数コンポーネントでは、props
を引数として受け取ります。
Propsの例
main.tsxとGreeting.tsxを以下のように変更してみましょう。
// main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import Greeting from './Greeting.tsx'
import './index.css'
createRoot(document.getElementById('root')).render(
<StrictMode>
<Greeting name="Alice" />
<Greeting name="Bob" />
</StrictMode>,
)
// Greeting.tsx
interface GreetingProps {
name: string;
}
// GreetingコンポーネントにPropsの型を指定
function Greeting({ name }: GreetingProps) {
return <h1>Hello, {name}!</h1>;
}
export default Greeting;
上記の例では、Greeting
コンポーネントがprops.name
を受け取り、それを表示しています。App
コンポーネントがGreeting
コンポーネントに名前を渡しているため、それぞれ「Hello, Alice!」と「Hello, Bob!」が表示されます。

4. コンポーネントの状態管理(State)
コンポーネントには状態(state)を持たせることができ、これによりコンポーネントの動的な振る舞いを制御できます。状態が変更されると、Reactは自動的にUIを再レンダリングします。
Stateを使ったコンポーネント
Counter.tsxを作成しmain.tsxから呼んでみましょう。
Counter.tsx
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0); // 状態を宣言
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントアップ</button>
</div>
);
}
export default Counter;
// main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import Counter from './Counter'
createRoot(document.getElementById('root')).render(
<StrictMode>
<Counter />
</StrictMode>,
)
- useState: Reactのフックの1つで、関数コンポーネントに状態を持たせるために使います。
useState(0)
は、カウントの初期値を0に設定しています。 - setCount: カウントを更新する関数です。ボタンをクリックすると
setCount
が呼ばれ、カウントが1増えます。

5. イベントハンドリング
Reactでは、DOM要素と同様にイベントハンドリングができます。たとえば、クリックイベントや入力の変更に反応する関数を簡単に設定できます。
イベントハンドリングの例
main.tsxを以下のように修正してください。
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
function ButtonClick() {
const handleClick = () => {
alert("ボタンがクリックされました");
};
return <button onClick={handleClick}>クリック</button>;
}
createRoot(document.getElementById('root')).render(
<StrictMode>
<ButtonClick />
</StrictMode>,
)
onClick
プロパティに関数を渡すことで、ボタンがクリックされたときにその関数が実行されます。この場合、ボタンをクリックするとアラートが表示されます。
6. コンポーネントの再利用
Reactコンポーネントは再利用可能で、さまざまな場所で使い回すことができます。コンポーネントを小さく分割し、それを組み合わせることで、複雑なアプリケーションを構築できます。
再利用可能なコンポーネントの例
main.tsxを以下のように修正してみてください。
import { createRoot } from 'react-dom/client';
import './index.css';
interface ButtonProps {
ButtonLabel: string;
}
function Button({ ButtonLabel }: ButtonProps) {
return <button>{ButtonLabel}</button>;
}
createRoot(document.getElementById('root')).render(
<div>
<Button ButtonLabel="OK" />
<Button ButtonLabel="Cancel" />
</div>
);
上記の例では、同じButton
コンポーネントが異なるlabel
プロパティを受け取って、「OK」ボタンと「Cancel」ボタンを表示しています。
7. コンポーネントのライフサイクル
コンポーネントは、ライフサイクルを持っています。つまり、コンポーネントがDOMにマウントされてからアンマウントされるまで、さまざまな段階があります。関数コンポーネントでは、useEffect
フックを使ってライフサイクルに応じた処理を行います。
useEffect
の例
Timer.tsxを作成しmain.tsxで呼んでみましょう。
// Timer.tsx
import React, { useState, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(s => s + 1);
}, 1000);
// コンポーネントがアンマウントされるときにクリーンアップ
return () => clearInterval(interval);
}, []);
return <div>経過時間: {seconds}秒</div>;
}
export default Timer;
// main.tsx
import { createRoot } from 'react-dom/client';
import './index.css';
import Timer from './Timer';
createRoot(document.getElementById('root')).render(
<div>
<Timer />
</div>
);
- useEffect: 副作用を処理するためのフック。ここでは、1秒ごとにカウントを更新するタイマーを設定しています。
- 第2引数の空配列
[]
により、コンポーネントのマウント時にのみ実行され、アンマウント時にクリーンアップ関数が呼ばれます。
以下のように経過時間がカウントアップされます。

8. コンポーネントを効率的に管理する
my-react-app/
├── index.html
├── package.json
├── vite.config.js
├── public/
└── src/
├── App.jsx
├── main.jsx
└── assets/
└── components/
作成したcomponentを効率的に管理し再利用性を高めるために、上記のようにsrcの直下にcomponentsというディレクトリを作成し、その中に、componentを作成する運用が一般的です。
もちろん、これは一例ですので、プロジェクトによってcomponentの管理方法は変わってきますが、1つパターンとしておさえておきましょう!
まとめ
Reactのコンポーネントは、Webアプリケーションを構築する上で非常に重要な要素です。コンポーネントを使うことで、UIを小さな再利用可能な部品に分けて管理でき、状態やイベント処理を追加することで動的なアプリケーションを構築できます。次のステップとして、より複雑な状態管理や、他のライブラリとの連携を学んで、Reactをさらに活用してみましょう。