Reactの初歩(コンポーネント、Hooks)とReact Routerを使ったルーティング
概要
ReactはFacebookが開発したUIライブラリで、再利用可能な「コンポーネント」を用いて効率的にユーザーインターフェースを構築できます
このチュートリアルを通し、以下に示すReactの基本機能を学び、簡単だけど有用な個人アプリ開発をできるようになってもらえればと思います
- 対象読者: Reactやフロントエンド開発が初めてのエンジニア
-
到達点:
- コンポーネント作成とPropsの利用
- 状態管理(useState)の理解
- React Routerを使ったページ遷移の実装
このチュートリアルを通じて、以下のようなシンプルなアプリを作成するスキルを身につけられます
このチュートリアルで作れるアプリ例
チュートリアルで学ぶReactの基礎を活用することで、以下のようなシンプルなサイトを構築可能です
1. 簡易レシピまとめサイト
-
例: クラシル
レシピを一覧表示し、材料や調理手順を詳細ページで確認できる仕組みを作れます
2. 単語帳学習サイト
-
例: mikan
覚えたい単語を登録し、一覧表示や個別ページで詳細情報(意味や例文)を確認できるサイトを作成できます
3. クイズサイト
-
例: QuizKnock
質問と選択肢を表示し、正答を確認できるシンプルなクイズアプリを構築できます
クイズリストを表示する機能や、詳細ページで質問の解答を確認する仕組みを作成可能です
このチュートリアルでやらないこと
このチュートリアルはReactの基本を学ぶミニマムなアプリを作れるようになるためのものです
そのため、以下のような高度な機能や技術は取り扱っていません
1. データの永続化やサーバーとの通信
-
例: ユーザーデータやTODOリストを保存して、ブラウザを閉じた後もデータを維持する機能
- Reactだけではデータを保存する機能(永続化)はありません
このような機能を追加するには、Firebaseやバックエンドサーバー(Node.js、Railsなど)との連携が必要です
- Reactだけではデータを保存する機能(永続化)はありません
2. ユーザー認証
-
例: ログイン・ログアウト機能や、認証済みユーザーのみがアクセスできるページの作成
- 認証機能を実現するには、Firebase AuthenticationやOAuthを活用した外部サービスの連携が必要です
3. 複雑なUIデザインやアニメーション
-
例: ドラッグ&ドロップ、動的なアニメーションや高度なレイアウトデザイン
- Material-UIなどのスタイリングライブラリは使用しません
これらの要素は別途チュートリアルを作成予定です
1. イントロダクション
1.1 Reactとは?
Reactは再利用可能なコンポーネントベースの設計を提供するUIライブラリであり、次のような特徴があります
- 学習コストが低い: コンポーネントとHooksを中心に簡潔に学べます
- 拡張性が高い: Material UI(Google) や Fluent UI(Microsoft) など多くの公式ライブラリが存在
- コンポーネントの再利用: 一度作成したコンポーネントを複数の場所で使い回せるため、効率的な開発が可能
1.2 環境構築
このセクションでは、Reactの開発を始めるための環境構築を行います
今回は、GitHubにあるReact開発用のdevcontainerを利用し、効率的に開発環境をセットアップします
-
GitHubリポジトリのクローン:
- ターミナルで以下のコマンドを実行してリポジトリをクローンしてください
git clone https://github.com/weworku/shared-devcon-react.git cd shared-devcon-react
- 以下のような構成となっていることを確認してください
/shared-devcon-react ├── /devcontainer │ └── devcontainer.json ├── Dockerfile ├── LICENSE ├── compose.yml ├── readMe.md └── work
- ターミナルで以下のコマンドを実行してリポジトリをクローンしてください
-
Devcontainerの起動:
- クローンしたフォルダ内には、React開発用のdevcontainer設定が含まれています
- Visual Studio Codeで
shared-devcon-react
フォルダを開き、Reopen in Container オプションを選択してdevcontainerに接続します
- 接続が完了すると、コンテナ内で必要な依存関係がインストールされ、Reactプロジェクトの開発が可能になります
-
Reactプロジェクトの作成:
- devcontainerに接続したら、ターミナルで以下のコマンドを実行し、新しいReactプロジェクトを初期化します
- このチュートリアルでは、Viteを使ってReactプロジェクトを作成します
npm create vite@latest sample-todo-app -- --template react-ts
- このコマンドにより、TypeScript対応のReactプロジェクトが
sample-todo-app
というフォルダ名で作成されます
-
プロジェクトのディレクトリに移動:
- 作成した
sample-todo-app
フォルダに移動し、依存関係をインストールしてプロジェクトを起動しますcd sample-todo-app npm install npm run dev -- --host 0.0.0.0
- 作成した
-
ブラウザで初期画面を確認:
-
npm run dev -- --host 0.0.0.0
を実行すると、ローカルサーバーが立ち上がり、ブラウザで初期のReactアプリが表示されます - 初期のReactアプリを表示するURL(通常は
http://localhost:5173
)を開き、Reactの初期画面が表示されることを確認しましょう
トラブルシューティング:
-
エラーが発生した場合:
-
npm install
が完了しているか確認してください - 使用しているNode.jsのバージョンが16以上であることを確認してください
-
-
これで、React開発環境のセットアップが完了しました
次のセクションでは、この初期アプリのコードを少し変更して、Reactの基本的な仕組みを体験していきます
2. ReactコンポーネントとPropsの基礎
2.1 コンポーネントとは?
Reactでは、アプリケーションのUIを小さな単位「コンポーネント」(Component)に分けて構築します
コンポーネントは以下の特徴を持ちます
- 再利用可能: 一度作成したUIを複数箇所で使用可能
- Propsの利用: データを親から子に渡して動的にUIを変更可能
2.2 開発準備
Reactアプリの初期設定では、デフォルトのCSSファイルが含まれています
このチュートリアルでは、スタイリングは目的ではないため、初期CSSを削除します
1. CSSファイルの削除
src
フォルダ内にある以下のCSSファイルを削除してください。
src/index.css
src/App.css
削除方法は、ファイルを右クリックして「削除」を選択するか、エディタ外で直接削除します
2. CSSのインポートを削除
index.tsx
および App.tsx
内にあるCSSのインポート文を削除してください
App.tsx
以下の行を削除してください
import './App.css';
2.3 TODOアイテムのコンポーネントを作成する
-
TodoItem
コンポーネントの作成
この例では、TodoItem
コンポーネントにcontent
というPropsを渡しています以下は、TODOリストの1項目を表示するシンプルなコンポーネントの例です
このファイルは、src/components
フォルダ内に保存してください// src/components/TodoItem.tsx // 現時点では使っていないため警告メッセージが出ます import React from 'react'; function TodoItem(props: { content: string }) { return <li>{props.content}</li>; } export default TodoItem;
-
解説: このコンポーネントは、
content
という文字列のPropsを受け取り、それを<li>
タグで表示するシンプルな構造です
2.4 AppコンポーネントでTODOリストを表示する
静的なTODOリストを表示する
- 次に、Appコンポーネントに静的なTODOリストを表示します
- ここでは、TODOの内容を配列として保持し、それをループ処理で表示する仕組みを導入します
-
App.tsx
に以下のコードを記述しますimport React from 'react'; import TodoItem from './components/TodoItem'; function App() { const todos = ["開発準備", "TODOアイテムのコンポーネントを作成する", "AppコンポーネントでTODOリストを表示する"]; return ( <div> <h1>TODO List</h1> <ul> {todos.map((todo, index) => ( <TodoItem key={index} content={todo} /> ))} </ul> </div> ); } export default App;
以下の画像のような表示になります
-
ポイント:
- 配列
todos
にTODO項目を定義しています -
map
関数を使い、TODO項目ごとにTodoItem
コンポーネントを呼び出し、表示しています - 注意: この段階では、配列に新しい項目を追加しても、表示は更新されません
- 配列
よければtodos
の変数の中を変えて、このチュートリアルに合わせてみてください
2.5 TODO追加フォームの作成
TodoForm
コンポーネントの作成
- 次に、新しいTODOを追加するための入力フォームを作成します
- 現時点のフォームはTODOリストに反映されず、動作が未完成の状態であることを確認します
-
src/components
フォルダに新しいファイルTodoForm.tsx
を作成し、以下のコードを記述します// src/components/TodoForm.tsx import React from 'react'; function TodoForm() { const handleAdd = () => { alert("TODO added!"); // 状態が無いため、まだ動作は確認のみ }; return ( <div> <input type="text" placeholder="Enter a new TODO"/> <button type="submit" onClick={handleAdd}>Add TODO</button> </div> ); } export default TodoForm;
Appコンポーネントにフォームを組み込む
-
App.tsx
を編集して、TODOリストの上にTodoForm
を追加しますimport React from 'react'; import TodoItem from './components/TodoItem'; import TodoForm from './components/TodoForm'; // Add: TodoForm.tsx への参照を追加 function App() { const todos = ["開発準備", "TODOアイテムのコンポーネントを作成する", "AppコンポーネントでTODOリストを表示する"]; return ( <div> <h1>TODO List</h1> {/* Add: TodoFromコンポーネントを追加 */} <TodoForm /> <ul> {todos.map((todo, index) => ( <TodoItem key={index} content={todo} /> ))} </ul> </div> ); } export default App;
以下の画像のような表示になります
-
ポイント:
-
TodoForm
は、入力欄とボタンを持っていますが、現時点ではTODOリストに入力内容が反映されません - ボタンを押しても、入力されたデータは
todos
配列に保存されないため、リストに追加されません
-
2.6 状態がないことを確認する
動作確認
-
TodoForm
の入力欄にテキストを入力し、「Add TODO」ボタンを押してみましょう - この段階では、TODOリストは更新されず、入力したデータが表示に反映されません
次のステップへの導入
- 現在、
todos
配列に新しい項目を追加しても表示が変わらない理由は、Reactで「状態」を管理していないためです - 次のセクションでは、Reactの
Hooks
を使って状態を管理し、TODOリストを動的に更新する方法を学びます
3. Hooks入門(useState)
このセクションでは、Reactの「Hooks」の一つであるuseState
を学んでいきます
前のセクションで作成したTODOアプリに状態管理を追加し、TODOリストを動的に更新できるようにします
3.1 Hooksの概要とuseState
ReactのHooksは、関数型コンポーネントで「状態管理」や「副作用」を扱うための機能です
このチュートリアルではuseState
を使用します
基本構文
const [state, setState] = useState(initialValue);
それぞれ変数は以下の意味になります
- state: 現在の状態の値
- setState: 状態を更新するための関数
- initialValue: 状態の初期値
3.2 TODOリストに状態を追加する
TODOリストを状態管理していくコードを追記していきます
useState
を使ってTODOリストを動的に管理します
- Appコンポーネントで
useState
を使い、TODOリストを状態として保持 -
TodoForm
からデータを受け取り、todos
を更新
// App.tsx
// import React from 'react'; // Delete
import { useState } from 'react'; // add: stateに必要なimportを追加
import TodoItem from './components/TodoItem';
import TodoForm from './components/TodoForm';
function App() {
// const todos = ["開発準備", "TODOアイテムのコンポーネントを作成する", "AppコンポーネントでTODOリストを表示する"]; // Delete
const [todos, setTodos] = useState(["開発準備", "TODOアイテムのコンポーネントを作成する", "AppコンポーネントでTODOリストを表示する"]); // Add: stateの追加
// stateの追加メソッドを定義
const addTodo = (todo: string) => {
setTodos([...todos, todo ]);
};
return (
<div>
<h1>TODO List</h1>
{/* Add: TodoFromコンポーネントを追加 */}
<TodoForm />
<ul>
{todos.map((todo, index) => (
<TodoItem key={index} content={todo} />
))}
</ul>
</div>
);
}
- 状態をもつ
todos
をuseState
で管理することで、TODOリストの変更がReactに認識されるようになります - この時点ではTODOリストの項目を追加する方法は未実装のため、次のステップで実装します
3.3 新しいTODOを追加する機能を実装
TodoForm
コンポーネントで入力した値をApp.tsx
の状態に追加する機能を実装します
TodoForm.tsx
TodoForm
コンポーネントを編集します
App.tsx
から状態と状態を変更するメソッドを受け取り、
新しいTODOを親コンポーネント(App.tsx
)に渡します
import { useState } from 'react'
function TodoForm(props: { addTodo: (todo: string) => void }) {
const [inputValue, setInputValue] = useState("") // Add: テキストボックスの入力を保持する
const handleAdd = () => {
// alert("TODO added!"); // Delete
props.addTodo(inputValue) // Add: 親コンポーネント管理のstateにTODO項目を追加
setInputValue("") // Add: TODOを保存したので入力欄をリセット
}
return (
<div>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)} // Add: 入力のたび、入力欄の状態を更新
placeholder="Enter a new TODO"
/>
{/* Add: ボタンクリック時にTODOを追加 */}
<button type="submit" onClick={handleAdd}>Add TODO</button>
</div>
)
}
export default TodoForm
3.4 動作確認
- アプリケーションを起動し、TODOリストが表示されることを確認します
-
TodoForm
にテキストを入力し、「Add TODO」ボタンを押します - 入力したテキストがリストに追加されることを確認します
次のステップ
ここまででできるようになったことは以下の通りです
- Reactの
useState
を使った状態管理 - TODOリストのデータを管理し、動的に表示する仕組みの実装
- 入力フォームからデータを取得してリストに追加する機能の実装
これらを通じて、ユーザーの入力やアクションに対して表示を動的に変更することができるようになりました
次のセクションでは、React Routerを使ってTODOリストにページ遷移の機能を追加します
4. ルーティングの基礎(React Router)
このセクションでは、Reactアプリケーションにページ遷移機能を追加するためのReact Routerの基礎を学びます
TODOアプリにルーティングを組み込み、リスト表示ページと詳細ページのような構造を実現します
4.1 React Routerとは?
-
React Routerの概要:
- React Routerは、Reactアプリケーションにルーティング機能を追加するためのライブラリです
- ページ遷移や動的なルーティングを簡単に実現できます
- ブラウザの履歴機能やブックマーク、リンク共有をサポートし、ユーザーに直感的なナビゲーション体験を提供します
-
主な機能:
- ページ間の移動
- 動的なルート(URLパラメータの使用)
- ネストされたルートの定義
-
このセクションで学ぶ内容:
- 基本的なルート設定
- ルート間のナビゲーション
- URLパラメータの使用
4.2 React Routerのインストール
-
インストールコマンド:
- React Routerをインストールします
npm install react-router-dom
4.3 ルートの定義
-
ルートの基本設定:
- アプリケーションのエントリーポイントである
App.tsx
にReact Routerを導入します - 以下のコードでReact Routerを設定します
- アプリケーションのエントリーポイントである
import { useState } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom' // Add: React Routerに必要なimport
import Home from './pages/Home' // Add: Homeページコンポーネントのimport
import TodoDetails from './pages/TodoDetails' // Add: TodoDetailsページコンポーネントのimport
function App() {
const [todos, setTodos] = useState([
"開発準備",
"TODOアイテムのコンポーネントを作成する",
"AppコンポーネントでTODOリストを表示する"
])
const addTodo = (todo: string) => {
setTodos([...todos, todo])
}
return (
<Router> {/* Add: Routerでアプリ全体をラップ */}
<Routes> {/* Add: Routesでルーティングを設定 */}
<Route path="/" element={<Home todos={todos} addTodo={addTodo} />} /> {/* Add: ホームページのルート */}
<Route path="/todo/:id" element={<TodoDetails todos={todos} />} /> {/* Add: 詳細ページのルート */}
</Routes>
</Router>
)
}
export default App
-
ポイント:
-
Router
を使用してアプリ全体をラップし、ルーティングを有効化 -
Routes
内にRoute
を定義し、パスに応じたコンポーネントを表示 - ホームページは
Home
、詳細ページはTodoDetails
を利用
-
4.4 ホームページの作成
-
Home.tsx:
- ホームページにTODOリストを表示し、各TODO項目へのリンクを追加します
-
src/pages
フォルダを作成し新しいファイルHome.tsx
を作成、以下のコードを記述します
// src/pages/Home.tsx
import { Link } from 'react-router-dom'
import TodoItem from '../components/TodoItem' // Add: TodoItem.tsx への参照を追加
import TodoForm from '../components/TodoForm' // Add: TodoForm.tsx への参照を追加
function Home(props: { todos: string[]; addTodo: (todo: string) => void }) {
return (
<div>
<h1>TODO List</h1>
<TodoForm addTodo={props.addTodo} /> {/* Add: TodoFormを表示 */}
<ul>
{props.todos.map((todo, index) => (
/* keyはReact内部で使い、indexはpropsとして渡す */
<TodoItem key={index} index={index} content={todo} />
))}
</ul>
</div>
)
}
export default Home
4.5 個別のTODO項目を表示するコンポーネントの修正
-
TodoItem.tsx:
-
TodoItem.tsx
を修正して、URLで個別のTodoに遷移できるようにします
-
// src/components/TodoItem.tsx
import React from 'react';
import { Link } from 'react-router-dom' // Add: todoへの遷移にLinkを利用
function TodoItem(props: { index: number, content: string }) {
return (
<li>
{/* Add: 各TODOにリンクを追加 */}
<Link to={`/todo/${props.index}`}>{props.content}</Link>
</li>
)
}
export default TodoItem
4.6 詳細ページの作成
-
TodoDetails.tsx:
- リストの項目をクリックすると詳細ページが表示されるようにします
-
src/pages
フォルダに新しいファイルTodoDetails.tsx
を作成、以下のコードを記述します
// src/pages/TodoDetails.tsx
import { useParams, Link } from 'react-router-dom' // Add: URLパラメータを取得するuseParamsとリンク用のLinkをimport
function TodoDetails(props: { todos: string[] }) {
const { id } = useParams<{ id: string }>() // Add: URLパラメータからIDを取得
const todo = props.todos[Number(id)] // Add: IDを元にTODOリストから項目を取得
if (!todo) {
return <p>TODO not found</p> // Add: 該当するTODOがない場合のエラーメッセージ
}
return (
<div>
<h1>TODO Details</h1>
<p>{todo}</p> {/* Add: TODOの詳細を表示 */}
<Link to="/">Back to TODO List</Link> {/* Add: ホームページへのリンク */}
</div>
)
}
export default TodoDetails
4.7 動作確認
- 確認する内容:
- アプリを起動し、ホームページでTODOリストが表示されることを確認
- 各TODO項目をクリックすると、詳細ページに遷移して内容が表示されることを確認
- 詳細ページに「Back to TODO List」のリンクがあり、クリックするとホームページに戻れることを確認
- 追加のポイント:
- URLパラメータを変更することで、動的に異なるTODOの詳細を表示できることを確認
4.8 次のステップ
これまでのチュートリアルを通じて、Reactの基礎(コンポーネント、状態管理、ルーティング)を使ったTODOリストアプリを完成させました
ここで学んだ内容を振り返ります
- 学んだこと:
- ReactのuseStateを使った状態管理
- データの動的な管理と表示
- React Routerを使ったページ遷移とURLパラメータの使用
これらを通じて、Reactを使ったシンプルなアプリケーションの構築手順を一通り学ぶことができました
5. 終わりに
次に進むステップとして、さらに高度なアプリケーション開発に挑戦してみましょう
以下はおすすめの学習内容です:
- UIコンポーネントライブラリの利用: Material UI(Google)やFluent UI(Microsoft)を使って、プロフェッショナルなデザインを取り入れる
- 高度な状態管理: ReduxやZustandを利用して、大規模なアプリケーションの複雑な状態を効率的に管理する
- APIとの通信: AxiosやFetch APIを使い、サーバーとデータをやり取りする仕組みを学ぶ
この記事で得た知識をベースに、さらに大きな目標に向けて一歩ずつ進んでいってください!
次回の記事では、Material UIを活用したスタイリッシュなUIデザインを取り入れる方法を紹介できればと思っています
お楽しみに!!
Discussion