Reactで作るTODOアプリ開発シリーズ第2回
この記事では
ReactのコンポーネントとJSX
について詳しく学習していきます。
前回は、Reactの基礎知識と開発環境の構築について学習しました。今回は、Reactの核となるコンポーネントとJSXについて、より深く理解していきましょう。
コンポーネントベース開発は、Reactの最大の特徴の一つです。小さな部品を組み合わせて大きなアプリケーションを作ることで、コードの再利用性と保守性を大幅に向上させることができます。
- コンポーネントの概念と種類(関数コンポーネント、クラスコンポーネント)
- JSXの詳細な文法と特徴
- Propsの受け渡し方法
- コンポーネントの分割と再利用
- 簡単なTODOアイテムコンポーネントの作成

コンポーネントベース開発の考え方を理解することで、より効率的で保守性の高いアプリケーションを作ることができるようになります!


TODOアプリ開発シリーズのまとめ記事はこちら
前回までのコード
第1回で作成したコードを確認しましょう。以下のファイル構成になっています。
ファイル構造
todo-app/
├── src/
│ ├── App.js
│ ├── App.css
│ ├── TodoItem.js
│ └── index.js
App.js
import React from 'react';
import './App.css';
import TodoItem from './TodoItem';
function App() {
return (
<div className="App">
<h1>React TODOアプリ</h1>
<div className="todo-list">
<TodoItem text="Reactを学ぶ" completed={false} />
<TodoItem text="TODOアプリを作る" completed={true} />
<TodoItem text="データベース連携" completed={false} />
</div>
</div>
);
}
export default App;
TodoItem.js
import React from 'react';
function TodoItem({ text, completed }) {
return (
<div className="todo-item">
<input
type="checkbox"
checked={completed}
readOnly
/>
<span style={{
textDecoration: completed ? 'line-through' : 'none'
}}>
{text}
</span>
</div>
);
}
export default TodoItem;
App.css
.App {
text-align: center;
padding: 20px;
max-width: 600px;
margin: 0 auto;
}
.todo-list {
margin-top: 20px;
}
.todo-item {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
padding: 10px;
border-bottom: 1px solid #eee;
}
.todo-item input[type="checkbox"] {
margin-right: 10px;
}
.todo-item span {
font-size: 16px;
}
コンポーネントの概念
実際に手を動かす前に、まずは必要な知識について解説をしていきます。
Reactのコンポーネントは、UIを構成する独立した部品です。HTMLの要素を拡張したようなもので、独自のロジックとスタイルを持つことができます。
コンポーネントの種類
Reactには主に2種類のコンポーネントがあります:
1. 関数コンポーネント(Function Component)
現在のReactでは、関数コンポーネントが推奨されています。シンプルで理解しやすく、Hooksを使用して状態管理も行えます。
function Welcome({ name }) {
return <h1>Hello, {name}!</h1>;
}
2. クラスコンポーネント(Class Component)
こちらは従来の書き方で、現在は関数コンポーネントが主流ですが、理解しておくと良いでしょう。
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
JSXの詳細な文法ルール
JSXは、JavaScriptの中にHTMLライクな記法を書くことができるReactの拡張構文です。
1. 要素のネスト
JSXでは、複数の要素を返す場合は、必ず1つの親要素で囲む必要があります。
// ❌ エラー:複数の要素を直接返している
function App() {
return (
<h1>タイトル</h1>
<p>説明文</p>
);
}
// ✅ 正しい:1つの親要素で囲んでいる
function App() {
return (
<div>
<h1>タイトル</h1>
<p>説明文</p>
</div>
);
}
// ✅ Fragmentを使用する方法(推奨)
function App() {
return (
<>
<h1>タイトル</h1>
<p>説明文</p>
</>
);
}
2. JavaScript式の埋め込み
JSXの中では、{}
を使ってJavaScriptの式を埋め込むことができます。
function App() {
const name = "React";
const isLoggedIn = true;
const items = ["アイテム1", "アイテム2", "アイテム3"];
return (
<div>
<h1>Hello, {name}!</h1>
<p>{isLoggedIn ? "ログイン中" : "ログアウト中"}</p>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
3. 属性の書き方
JSXでは、HTMLの属性名が少し異なります。
function App() {
const className = "container";
const style = { backgroundColor: "blue", color: "white" };
return (
<div
className={className} // classではなくclassName
style={style} // オブジェクトとして渡す
data-testid="app" // カスタム属性はそのまま
>
コンテンツ
</div>
);
}
Propsの受け渡し
Propsは、親コンポーネントから子コンポーネントにデータを渡すための仕組みです。
Propsの基本
// 親コンポーネント
function App() {
return (
<div>
<TodoItem text="買い物に行く" completed={false} priority="high" />
<TodoItem text="本を読む" completed={true} priority="low" />
</div>
);
}
// 子コンポーネント
function TodoItem({ text, completed, priority }) {
return (
<div className={`todo-item priority-${priority}`}>
<input type="checkbox" checked={completed} readOnly />
<span style={{ textDecoration: completed ? 'line-through' : 'none' }}>
{text}
</span>
</div>
);
}
デフォルト値の設定
Propsにデフォルト値を設定することで、値が渡されなかった場合の処理を書くことができます。
function TodoItem({ text, completed = false, priority = "medium" }) {
return (
<div className={`todo-item priority-${priority}`}>
<input type="checkbox" checked={completed} readOnly />
<span style={{ textDecoration: completed ? 'line-through' : 'none' }}>
{text}
</span>
</div>
);
}
スプレッド構文の使用
スプレッド構文を使用することで、オブジェクトのプロパティを展開して渡すことができます。
function App() {
const todoData = {
text: "買い物に行く",
completed: false,
priority: "high",
createdAt: "2024-01-01"
};
return (
<div>
<TodoItem {...todoData} />
</div>
);
}
【実践】コンポーネントの分割と再利用
それでは、ここからは実際に手を動かして、新しいコンポーネントを作成していきましょう。
大きなコンポーネントを小さな部品に分割することで、コードの再利用性と保守性を向上させることができます。
1. TodoListコンポーネントの作成
src/TodoList.js
ファイルを新規作成し、以下のコードを記述してください。
import React from 'react';
import TodoItem from './TodoItem';
function TodoList({ todos }) {
return (
<div className="todo-list">
{todos.map((todo, index) => (
<TodoItem
key={index}
text={todo.text}
completed={todo.completed}
priority={todo.priority}
/>
))}
</div>
);
}
export default TodoList;
2. TodoHeaderコンポーネントの作成
src/TodoHeader.js
ファイルを新規作成し、以下のコードを記述してください。
import React from 'react';
function TodoHeader({ title, totalCount, completedCount }) {
return (
<div className="todo-header">
<h1>{title}</h1>
<div className="todo-stats">
<span>総数: {totalCount}</span>
<span>完了: {completedCount}</span>
<span>未完了: {totalCount - completedCount}</span>
</div>
</div>
);
}
export default TodoHeader;
3. App.jsの修正
既存のsrc/App.js
を以下のように修正してください。
import React from 'react';
import './App.css';
import TodoHeader from './TodoHeader';
import TodoList from './TodoList';
function App() {
const todos = [
{ text: "Reactを学ぶ", completed: false, priority: "high" },
{ text: "TODOアプリを作る", completed: true, priority: "medium" },
{ text: "データベース連携", completed: false, priority: "low" },
{ text: "デプロイする", completed: false, priority: "medium" }
];
const completedCount = todos.filter(todo => todo.completed).length;
return (
<div className="App">
<TodoHeader
title="React TODOアプリ"
totalCount={todos.length}
completedCount={completedCount}
/>
<TodoList todos={todos} />
</div>
);
}
export default App;
4. スタイルの追加
既存のsrc/App.css
に以下のスタイルを追加してください。
.todo-header {
margin-bottom: 30px;
}
.todo-stats {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 10px;
font-size: 14px;
color: #666;
}
.todo-stats span {
padding: 5px 10px;
background-color: #f5f5f5;
border-radius: 15px;
}
.priority-high {
border-left: 4px solid #ff4757;
}
.priority-medium {
border-left: 4px solid #ffa502;
}
.priority-low {
border-left: 4px solid #2ed573;
}
5. TodoItem.jsの更新
既存のsrc/TodoItem.js
を以下のように更新してください(priorityプロパティを追加)。
import React from 'react';
function TodoItem({ text, completed, priority = "medium" }) {
return (
<div className={`todo-item priority-${priority}`}>
<input
type="checkbox"
checked={completed}
readOnly
/>
<span style={{
textDecoration: completed ? 'line-through' : 'none'
}}>
{text}
</span>
</div>
);
}
export default TodoItem;
動作確認
実装が完了したら、開発サーバーが起動している状態でブラウザを確認してください。以下のような表示が確認できます。


- タイトルと統計情報(総数、完了数、未完了数)
- 優先度に応じた色分けされたTODOアイテム(左端の色付きボーダー)
FAQ
まとめ
今回は、ReactのコンポーネントとJSXについて詳しく学習しました。
コンポーネントベース開発により、UIを小さな部品に分割して開発することで、コードの再利用性と保守性を大幅に向上させることができます。
JSXの詳細な文法とPropsの受け渡し方法を理解することで、より柔軟で拡張性の高いコンポーネントを作成できるようになりました。



次回は、Reactでの状態管理について学習していきます。useStateフックを使って、動的なTODOアプリケーションを作成していきましょう!
この記事が少しでもお役に立ったなら何よりです。次回もお楽しみに!
コメント