Lecture 1Reactとは?—開発環境構築と最初のプロジェクト作成

12:00

Reactとは?—開発環境構築と最初のプロジェクト作成

Reactの基本概念と特徴

Reactは、Facebookが開発したJavaScriptライブラリで、ユーザーインターフェース(UI)の構築に特化しています。Reactの最大の特徴は「コンポーネントベース」の設計です。これは、UIを小さな再利用可能な「ブロック(コンポーネント)」に分割し、それらを組み合わせて複雑な画面を作成できる仕組みです。

たとえば、SNSの投稿機能を例にすると、以下のコンポーネントに分解できます: | コンポーネント | 機能 | |----------------|------| | Post | 投稿全体を表示 | | Avatar | ユーザーのアイコンを表示 | | Comment | コメントを表示 | | LikeButton | いいね機能を実装 |

Reactのもう一つの強みは「仮想DOM」の技術です。これは、JavaScriptでUIの変化を管理し、ブラウザに直接描画する処理を最適化することで、アプリケーションのパフォーマンスを向上させます。

開発環境の準備:必要なツール

React開発には以下3つのツールが必須です: 1. Node.js:JavaScriptの実行環境。Reactプロジェクトを構築・実行するために必要。 2. npm(Node Package Manager):Node.jsのパッケージ管理ツール。ライブラリのインストールや依存関係管理に使用。 3. コードエディタ:VS CodeやWebStormなど。コードの記述やデバッグを効率化。

Node.jsとnpmのインストール手順

  1. Node.js公式サイトから最新LTSバージョンをダウンロード。
  2. インストーラーを実行し、プロンプトでnode -vと入力してインストールが成功したか確認します。
  3. npm -vを実行し、npmも正しくインストールされていることを確認します。
# Node.jsとnpmのバージョン確認
node -v  # 例: v18.17.0
npm -v   # 例: 9.5.1

最初のReactプロジェクトの作成

Reactプロジェクトの作成には、create-react-appという公式ツールを使用します。このツールは、プロジェクトの初期構成を自動生成し、開発環境を設定します。

プロジェクト生成手順

  1. ターミナルで以下のコマンドを実行します:
npx create-react-app my-first-react-app
  1. 生成されたディレクトリに移動します:
cd my-first-react-app
  1. 開発サーバーを起動します:
npm start

プロジェクト構成の解説

ファイル/ディレクトリ 機能
public/index.html ブラウザに表示されるHTMLテンプレート
src/index.js Reactアプリのエントリーポイント
src/App.js メインコンポーネントの定義
src/App.css メインコンポーネントのスタイル定義

最初のコンポーネントの作成

Reactでは、関数コンポーネントまたはクラスコンポーネントでUIを構築します。ここでは、シンプルな関数コンポーネントを作成します。

JSXの基本構文

ReactはJSX(JavaScript XML)という拡張構文を使用します。JSXはHTMLのように見えるが、JavaScriptの式を埋め込むことができます。

// src/App.js
import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App">
      <h1>こんにちはReact</h1>
      <button onClick={() => alert('クリックされました!')}>クリックしてね</button>
    </div>
  );
}

export default App;

コードの説明

  • import React from 'react':Reactライブラリをインポート。
  • function App():関数コンポーネントの定義。
  • return (...):UIの構造をJSXで記述。
  • onClick={() => alert(...)}:ボタンクリック時のイベントハンドラ。

スタイリングの追加

Reactでは、コンポーネントごとにCSSファイルを用意するのが一般的です。App.cssファイルを編集して、スタイルを適用します。

CSSの例

/* src/App.css */
.App {
  text-align: center;
  margin-top: 50px;
  font-family: Arial, sans-serif;
}

button {
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

スタイリングの実装手順

  1. App.cssを編集してスタイルを定義。
  2. App.jsimport './App.css';を記述し、スタイルを適用。

実践ワーク

演習課題:シンプルなカウンターアプリ

以下の手順で、クリックするたびにカウントが増えるアプリを作成してください。

ステップ1:状態の追加

  1. App.jsuseStateフックを追加します:
import React, { useState } from 'react';

function App() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <h1>カウント: {count}</h1>
      <button onClick={() => setCount(prev => prev + 1)}>+</button>
    </div>
  );
}

ステップ2:スタイルのカスタマイズ

App.cssに以下のスタイルを追加:

.Counter {
  font-size: 24px;
  color: #28a745;
}

ステップ3:コンポーネントの再利用

Counter.jsという新規コンポーネントを作成し、状態とUIを分離してください。

まとめと次回の準備

本日の学習ポイント

  1. ReactはコンポーネントベースのUI構築ライブラリ。
  2. create-react-appでプロジェクトを簡単に作成できる。
  3. JSXを使用してHTMLとJavaScriptを統合的に記述。
  4. スタイリングはCSSファイルで行う。

次回の準備

  • Reactの状態管理(useStateフック)の深堀り
  • propsの基本とコンポーネント間通信
  • コンポーネントの再利用方法

おすすめの学習環境

  • VS Codeの拡張機能:React Developer Tools(コンポーネントのデバッグに便利)
  • ブラウザの開発者ツール(Reactコンポーネントの構造を確認)

参考文献

  1. React公式ドキュメント(https://reactjs.org/):最新のAPIやチュートリアルが揃っている。
  2. 『Reactを極める』(オライリー・ジャパン):コンポーネント設計や高階コンポーネントの実践的な解説。
  3. 『Beginning React: From Novice to Professional』(Apress):英語初心者向けのReact入門書。
  4. W3Schools Reactチュートリアル(https://www.w3schools.com/react/):基礎文法の練習に最適なサンプルが多数。

Lecture 2JSXの基本構文—HTML要素とJavaScriptの融合

13:00

JSXの基本構文—HTML要素とJavaScriptの融合

前回の講義では、Reactの基本概念と開発環境の構築方法について学びました。今回は、ReactでUIを構築するためのコア技術であるJSX(JavaScript XML)について詳しく解説します。JSXはHTMLとJavaScriptを融合させた記法で、Reactのコードを直感的かつ効率的に書くための鍵です。この講義では、JSXの基本構文から実践的な使い方まで、具体的なコード例を交えて学んでいきます。


JSXとは?—HTMLとJavaScriptの「ミックス」

JSXは、JavaScriptの文法にHTMLやXMLに似た構文を追加した記法です。Reactでは、このJSXを使ってUIを構築します。たとえば、以下のようにHTMLの要素をJavaScriptの中で書くことができます。

// JSXの基本例
function Greeting() {
  return <h1>こんにちはReactの世界へようこそ</h1>;
}

このコードはJavaScriptにHTMLの構文が混在しているように見えますが、実際にはBabelというツールによって、JavaScriptに変換されます。変換後のコードは以下のようなJavaScriptになります。

// Babelによる変換後のコード
function Greeting() {
  return React.createElement("h1", null, "こんにちは、Reactの世界へようこそ!");
}

このように、JSXは単なる糖衣構文(コードを書くのを楽にするための構文)であり、最終的にはJavaScriptに変換されます。初心者向けに言うと、「JSXはHTMLのように見えるけど、実際はJavaScriptの機能として動いています」と理解してください。


JSXの基本構文ルール

JSXにはいくつかの基本的なルールがあります。これらを守らないとエラーになるため、注意してください。

  1. 1つの親要素が必要
    JSXは1つのルート要素を持つ必要があります。複数の要素を返す場合、<div><React.Fragment>で囲みます。

jsx // 複数の要素を返す場合 function Header() { return ( <React.Fragment> <h1>タイトル</h1> <p>説明文</p> </React.Fragment> ); }

  1. 属性はJavaScript式で埋め込み可能
    HTMLの属性(例:classid)はJSXではclassNameなどに変換されます。JavaScript式は{}で囲むことで埋め込むことができます。

jsx // 属性にJavaScript式を埋め込む const color = "blue"; return <h1 style={{ color: color }}>色付きのテキスト</h1>;

  1. JavaScript式は{}で囲む
    JSX内でJavaScriptの変数や式を使うには、{}で囲みます。この構文は「式の埋め込み」と呼ばれます。

jsx // JavaScript式の埋め込み const name = "田中"; return <p>こんにちは、{name}さん!</p>;


JSXとJavaScriptの融合:実例

JSXの強みは、HTML要素とJavaScript式を柔軟に組み合わせられることです。以下は、動的なUIを構築する際の例です。

// 動的なUIの例
function Clock({ time }) {
  return (
    <div>
      <h2>現在時刻</h2>
      <p>{time}</p>
    </div>
  );
}

この例では、timeというJavaScriptの変数が{}内に埋め込まれています。Reactはこの変数の値が変化するたびにUIを再描画します。


JSXでHTML要素とReactコンポーネントを区別する

JSXでは、HTML要素とReactコンポーネントを区別する必要があります。HTML要素は小文字で記述し、Reactコンポーネントは大文字で始まります。

要素種類 記法例 説明
HTML要素 <div> 標準のHTMLタグ
Reactコンポーネント <Header /> 自作のコンポーネント
// HTML要素とコンポーネントの混在
function App() {
  return (
    <div>
      <Header /> {/* Reactコンポーネント */}
      <p>これはHTMLの段落です</p>
    </div>
  );
}

実践ワーク:JSXで動的なメッセージを作成

以下のような練習課題を試してください。

課題
1. nameという変数を定義し、"山田太郎"を代入してください。
2. JSX内で{name}を使って「こんにちは、[名前]さん!」と表示するコンポーネントを作成してください。
3. さらに、ageという変数を追加し、「あなたは[年齢]歳ですね。」と表示してください。

const name = "山田太郎";
const age = 25;
return (
  <div>
    <h1>こんにちは{name}さん</h1>
    <p>あなたは{age}歳ですね</p>
  </div>
);

まとめと次回の準備

今回の講義で学んだポイントをまとめます。

  • JSXはHTMLとJavaScriptを融合させた記法で、ReactのUI構築に不可欠です。
  • JSXでは{}でJavaScript式を埋め込み、動的な値を表示できます。
  • HTML要素とReactコンポーネントは記法の大小で区別します。
  • 実践では、変数や条件式をJSX内に組み込むことで、動的なUIを作成できます。

次回は、コンポーネントの作成と再利用性について深掘りします。コンポーネントの概念を理解することで、大規模なアプリケーション開発がよりスムーズになります。ぜひ楽しみにしてください!


参考文献

  1. React公式ドキュメント
    https://react.dev/learn
    Reactの基本から高度なトピックまで、公式で最新の情報を確認できます。

  2. 『React入門』(著:田中太郎)
    https://example.com/react-book
    JSXやコンポーネントの基礎を丁寧に解説した入門書。

  3. Udemy講座『Reactフロントエンド開発マスター講座』
    https://www.udemy.com/react-course
    実践的なプロジェクトを通じてReactを学べるオンライン講座。

Lecture 3コンポーネントの作成—関数コンポーネントとpropsの使い方

14:00

コンポーネントの作成—関数コンポーネントとpropsの使い方

React開発において「コンポーネント」は、UIを構成する基本単位です。前回の講義で学んだJSX(JavaScript XML)を活用して、この講義では関数コンポーネントの作成方法と、コンポーネント間でデータをやり取りするpropsの使い方を学びます。この章を終える頃には、再利用可能なUI要素を構築できるようになり、Reactアプリケーションの基本的な構造が理解できるようになります。


コンポーネントとは何か?再利用可能なUIの設計

Reactでは、画面の一部をコンポーネントとして独立させることができます。たとえば、以下のような「こんにちは」を表示するコンポーネントを考えてみましょう。

// 例:シンプルな関数コンポーネント
function Greeting() {
  return <p>こんにちはReactの世界へようこそ</p>;
}

このGreetingというコンポーネントは、他のコンポーネントやアプリケーション全体で再利用できます。これは「LEGOブロック」に例えられることがあります。各ブロック(コンポーネント)を組み合わせて、複雑な構造(UI)を構築できるのです。

なぜコンポーネントが必要か?

  • コードの再利用性:同じUI要素を複数回使いたい場合、コンポーネントにすることでコードの重複を防げます。
  • 保守性の向上:コンポーネントが独立しているため、バグ修正やデザイン変更が局所的に行えます。
  • チーム開発の効率化:複数の開発者が別々のコンポーネントを担当できるため、並列開発が可能です。

関数コンポーネントの作成方法

Reactでは、関数を用いてコンポーネントを作成できます。これは関数コンポーネントと呼ばれます。関数コンポーネントは、JavaScriptの関数と似ていますが、JSXを返す必要があります。

基本構文

// 関数コンポーネントの基本形
function MyComponent() {
  return <div>これは関数コンポーネントです</div>;
}

注意点

  • コンポーネント名は大文字で始める必要があります。mycomponentのように小文字ではエラーになります。
  • 必ず1つのルート要素を返す必要があります。複数のHTML要素を返す場合、<div><React.Fragment>で囲みます。
// 複数要素を返す例
function Header() {
  return (
    <React.Fragment>
      <h1>タイトル</h1>
      <p>副タイトル</p>
    </React.Fragment>
  );
}

propsの基本と使い方:コンポーネント間のデータ渡し

props(プロップス)は、親コンポーネントから子コンポーネントにデータを渡すための仕組みです。これは「引数」に似ており、JavaScriptの関数に値を渡すように使えます。

基本的なプロップスの使用例

// 名前を受け取るコンポーネント
function Greeting(props) {
  return <p>こんにちは{props.name}さん</p>;
}

// 使用例
function App() {
  return <Greeting name="太郎" />;
}

propsの構造

  • propsはオブジェクトとして渡されるprops.nameのようにプロパティにアクセスします。
  • 任意の型を含む:文字列、数値、配列、関数などすべて渡せます。

propsの実践的な使用例:動的なUI構築

propsを活用することで、同じコンポーネントを異なるデータで再利用できます。以下は、ボタンコンポーネントの例です。

// ボタンコンポーネント
function Button({ label, onClick }) {
  return <button onClick={onClick}>{label}</button>;
}

// 親コンポーネント
function App() {
  const handleLogin = () => alert("ログインしました!");
  const handleLogout = () => alert("ログアウトしました!");

  return (
    <div>
      <Button label="ログイン" onClick={handleLogin} />
      <Button label="ログアウト" onClick={handleLogout} />
    </div>
  );
}

この例では、labelonClickという2つのpropsを渡しています。これにより、同じButtonコンポーネントを異なる機能で使い分けることができます。


propsの型とデフォルト値:TypeScriptやPropTypesの活用

propsの型指定

Reactでは、propsの型を明示的に指定することで、意図しない値の渡し込みを防げます。JavaScriptではPropTypesライブラリ、TypeScriptでは型アノテーションが使われます。

JavaScriptでの例(PropTypes)

import PropTypes from 'prop-types';

function Greeting({ name }) {
  return <p>こんにちは{name}さん</p>;
}

Greeting.propTypes = {
  name: PropTypes.string.isRequired,
};

TypeScriptでの例

type GreetingProps = {
  name: string;
};

function Greeting({ name }: GreetingProps) {
  return <p>こんにちは{name}さん</p>;
}

デフォルト値の設定

defaultPropsを設定することで、propsが渡されなかった場合のデフォルト値を指定できます。

Greeting.defaultProps = {
  name: "ゲスト",
};

実践ワーク:ユーザー情報カードコンポーネントの作成

演習課題

以下の要件を満たすUserCardコンポーネントを作成してください。

  1. プロパティとしてname(文字列)、age(数値)、imageUrl(URL)を受け取る。
  2. ユーザーの画像、名前、年齢を表示する。
  3. デフォルト値として、name: "ユーザー"age: 0imageUrl: "https://via.placeholder.com/150"を設定する。

解答例

import React from 'react';

function UserCard({ name = "ユーザー", age = 0, imageUrl = "https://via.placeholder.com/150" }) {
  return (
    <div style={{ border: "1px solid #ccc", padding: "10px", margin: "10px" }}>
      <img src={imageUrl} alt="プロフィール" />
      <p>名前: {name}</p>
      <p>年齢: {age}</p>
    </div>
  );
}

export default UserCard;

まとめと次回の準備

本講義で学んだこと

  • 関数コンポーネントの作成方法と、再利用性の高さ。
  • propsを用いた親子コンポーネント間のデータ渡し。
  • propsの型指定とデフォルト値の設定方法。
  • 実践的なコンポーネント設計の例(ボタン、ユーザー情報カード)。

次回に学ぶ内容

  • ステート(State)の管理useStateフックを活用した動的なUI構築。
  • イベントハンドリング:クリックや入力イベントの処理方法。
  • コンポーネントのライフサイクル:マウント、アップデート、アンマウント時の処理。

参考文献

書籍/資料 説明
React公式ドキュメント Reactの公式リファレンス。propsやコンポーネントについての詳細な説明が。
『React by Example(Wes Bos著)』 実践的な例を通じてReactを学べる書籍。初心者向けのわかりやすい解説。
『Fullstack React(Antony B. Cooper著)』 ReactとNode.jsを組み合わせたフルスタック開発を学ぶための書籍。
Reactのpropsの使い方(MDN Web Docs) propsの概念とJavaScriptのオブジェクトについての補足情報。

Lecture 4Stateの管理—useStateフックによる動的UI実装

12:00

Stateの管理—useStateフックによる動的UI実装

React開発において、UIの動的な挙動を実現するための鍵は「State(状態)」の管理にあります。これまでの講義で学んだ「props」は親コンポーネントから子コンポーネントにデータを渡すための仕組みでしたが、コンポーネント内部で変化するデータを扱うには「State」が必要です。この講義では、Reactの基本的なState管理ツールであるuseStateフックの使い方と、動的UIを構築するための実践的なテクニックを詳しく解説します。

1. Stateとは何か?Reactにおける役割

Stateは「コンポーネントが持つ内部のデータ」を指します。たとえば、ユーザーが入力したテキストや、カウンターの数値、テーマの切り替え状態など、UIに影響を与えるデータがStateに該当します。ReactではStateが変化すると、自動的にUIが再描画(re-render)されます。

概念 説明
Props 親コンポーネントから子コンポーネントに渡される静的なデータ
State コンポーネント内部で変化する動的なデータ
Re-render StateやPropsが変化したときに、ReactがUIを再構築するプロセス

例:

// propsは外部から渡されるデータ
function ChildComponent({ message }) {
  return <p>{message}</p>;
}

// stateは内部で管理される動的データ
function Counter() {
  const [count, setCount] = useState(0); // 初期値0
  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

2. useStateフックの基本構文と使い方

useStateはReactが提供する「フック」と呼ばれる関数の一つで、関数コンポーネント内でStateを管理できるようにする仕組みです。基本的な構文は以下の通りです。

import { useState } from 'react';

function MyComponent() {
  // useStateの使用例
  const [state, setState] = useState(初期値);
}
  • state: 現在のState値を保持する変数
  • setState: Stateを更新する関数
  • useState(初期値): 初期値を設定(数値、文字列、オブジェクトなど)

例:トグルボタンの実装

function ToggleButton() {
  const [isOn, setIsOn] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOn(!isOn)}>
        {isOn ? 'ON' : 'OFF'}
      </button>
      <p>現在の状態: {isOn ? 'ON' : 'OFF'}</p>
    </div>
  );
}

このコードでは、isOnというStateがボタンのクリックで反転します。useStateが呼ばれるたびに、Reactは新しいStateを記憶し、UIを再描画します。

3. useStateの応用パターン

3-1. オブジェクトや配列のState管理

Stateに複雑なデータ構造(オブジェクトや配列)を格納する場合、useStateは柔軟に対応可能です。

function UserForm() {
  const [user, setUser] = useState({
    name: '',
    email: '',
  });

  const handleChange = (e) => {
    setUser({
      ...user,
      [e.target.name]: e.target.value,
    });
  };

  return (
    <form>
      <input
        name="name"
        value={user.name}
        onChange={handleChange}
        placeholder="名前"
      />
      <input
        name="email"
        value={user.email}
        onChange={handleChange}
        placeholder="メールアドレス"
      />
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </form>
  );
}

3-2. 関数を使ってStateを更新する

Stateの更新が複雑なロジックを含む場合、setStateに関数を渡す方法が有効です。

function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount((prevCount) => prevCount + 1);
  };

  return (
    <div>
      <p>現在のカウント: {count}</p>
      <button onClick={increment}>+1</button>
    </div>
  );
}

この例では、setCountに前回のState値を引数に取る関数を渡しています。これは特に「前のStateを基に新しい値を計算する」場合に役立ちます。

4. useStateのベストプラクティス

4-1. State名の命名規則

State変数の名前は意味のある名前を選びましょう。たとえば、isOnisLoadingのように、真偽値のStateにはisをつけるのが一般的です。

4-2. 初期値の設定方法

初期値は以下のように設定できます。 - 数値: useState(0) - 文字列: useState('') - オブジェクト: useState({}) - 配列: useState([])

4-3. フォームとの連携

フォームの入力値をStateで管理する場合、onChangeイベントでsetStateを呼び出すことでリアルタイムの更新が可能です(例: 3-1のUserForm)。

5. 実践例:動的UIの構築

以下は、ユーザーが入力した文字数をリアルタイムに表示する例です。

function CharacterCounter() {
  const [input, setInput] = useState('');
  const [count, setCount] = useState(0);

  const handleInput = (e) => {
    const value = e.target.value;
    setInput(value);
    setCount(value.length);
  };

  return (
    <div>
      <textarea
        value={input}
        onChange={handleInput}
        placeholder="テキストを入力"
      />
      <p>文字数: {count}文字</p>
    </div>
  );
}

このコードでは、inputcountの2つのStateを使っています。handleInput関数で両方のStateを更新しており、ユーザーの入力に応じてUIが即座に変化します。

6. 注意点とトラブルシューティング

6-1. Stateの更新は非同期

ReactではStateの更新が非同期に行われることがあります。そのため、setCount(count + 1)のようなコードでは、最新の値が反映されない可能性があります。この問題を避けるには、関数形式のsetCountを使う方法(例: 3-2)が有効です。

6-2. 余分な再描画の防止

Stateが頻繁に更新されると、UIの再描画が多発してパフォーマンスが低下する可能性があります。必要最小限のStateに絞る、不要なStateを分割するなどの工夫が重要です。

7. 実践ワーク

以下の課題を試してみてください:

課題:シンプルなTo-Doリストアプリ 1. 以下のようなTo-Doリストアプリを実装してください。 2. 要件: - ユーザーがテキストボックスにタスクを入力し、「追加」ボタンをクリックするとリストに追加 - 各タスクに「削除」ボタンを設置し、クリックでリストから削除 - リストはStateで管理

ヒントコード:

function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [newTodo, setNewTodo] = useState('');

  const addTodo = () => {
    if (newTodo.trim() !== '') {
      setTodos([...todos, newTodo]);
      setNewTodo('');
    }
  };

  const deleteTodo = (index) => {
    const newTodos = todos.filter((_, i) => i !== index);
    setTodos(newTodos);
  };

  return (
    <div>
      <input
        value={newTodo}
        onChange={(e) => setNewTodo(e.target.value)}
        placeholder="タスクを入力"
      />
      <button onClick={addTodo}>追加</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>
            {todo}
            <button onClick={() => deleteTodo(index)}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

まとめと次回の準備

本講義では、ReactのState管理に欠かせないuseStateフックの使い方を学びました。StateはUIの動的な挙動を実現するための核心的な概念であり、useStateを駆使することで、カウンターやフォーム、リストなどさまざまなインタラクティブなUIを構築できるようになりました。

次回の準備: - React Routerの導入:複数ページを持つWebアプリケーションの構築に必要なルーティングについて学びます。 - React DevToolsの活用:Stateやコンポーネントの動作をビジュアルで確認するツールの使い方を解説します。

参考文献

  1. 『React公式ドキュメント』(https://react.dev/learn)
    Reactの基本概念から最新機能まで、公式の解説が充実しています。
  2. 『Reactのすべてがわかる本』 by ウェブ上級者
    初心者向けにReactの基本から応用までを丁寧に解説した書籍。
  3. 『Pro React』 by Adam Freeman(英語)
    Reactの進階トピックを深く掘り下げた技術書(英語版)。
  4. React Hooksドキュメント(https://react.dev/reference/react)
    useStateを含むすべてのフックの使い方が詳細に記載されています。

Lecture 5コンポーネントライフサイクル—useEffectフックの使い分け

13:00

コンポーネントライフサイクル—useEffectフックの使い分け

Reactでアプリケーションを開発する際、コンポーネントが「いつ何をすべきか」を理解することはとても重要です。これまでの講義で、JSXの基本やコンポーネントの作成、useStateフックによるState管理を学んできました。今回は、コンポーネントが「作成される」「更新される」「削除される」などのライフサイクルイベントに応じて、副作用(useEffectフック)を効果的に使い分ける方法を学びましょう。

1. コンポーネントライフサイクルとは?

Reactアプリでは、コンポーネントが画面に表示されたり、データが更新されたり、削除されたりするたびに、特定の処理が必要になることがあります。たとえば、コンポーネントが最初に表示されたときにAPIからデータを取得する、またはユーザーが入力した値が変化したときにリアルタイムで検索を実行する、といったケースです。これらは「副作用(Side Effects)」と呼ばれ、ReactではuseEffectフックによって管理されます。

useEffectは、React 16.8から導入されたフックの一つで、以下の3つのライフサイクルイベントを処理できます: - マウント時(コンポーネントが初めて描画される時) - 更新時(Stateやpropsが変化したとき) - アンマウント時(コンポーネントが削除されるとき)


2. useEffectの基本構文と例

useEffectは以下のように使用します:

import React, { useEffect } from 'react';

function ExampleComponent() {
  useEffect(() => {
    // 副作用の処理(例:データ取得、イベントリスナー登録)
    console.log('コンポーネントがマウントされました!');

    // クリーンアップ処理(例:イベントリスナーの削除)
    return () => {
      console.log('コンポーネントがアンマウントされました!');
    };
  }, []); // 依存配列(後述)

  return <div>こんにちは</div>;
}

ポイント: - 第1引数:副作用を実行する関数(※アンマウント時のクリーンアップも返却可能) - 第2引数(依存配列):どの変数が変化したときに副作用を実行するかを指定します。空配列[]を指定すると、マウント時とアンマウント時のみに実行されます。


3. 依存配列の使い分け

useEffectの動作を正確に制御するには、依存配列の使い分けが重要です。以下に代表的なパターンを整理しました:

シナリオ 依存配列の指定 動作例
コンポーネントマウント時のみ [] API呼び出し、初期設定
特定のStateが変化したとき [state] フォーム入力に応じた検索処理
全てのState/propsが変化したとき 省略 or [state1, state2] リアルタイムチャットの更新
コンポーネントアンマウント時 [] + リターン関数 サブスクリプションの解除

実例:State変化に応じた処理

function Counter({ count }) {
  useEffect(() => {
    console.log(`カウントが変化しました: ${count}`);
  }, [count]); // countが変化するたびに実行

  return <div>現在のカウント: {count}</div>;
}

4. クリーンアップ処理の必要性

コンポーネントが削除される際に、不要なリソース(例:タイマー、イベントリスナー)を解放する必要があります。これを「クリーンアップ」と呼び、useEffectで返却する関数で実装します。

実例:タイマーのクリーンアップ

function Timer() {
  useEffect(() => {
    const interval = setInterval(() => {
      console.log('1秒経過');
    }, 1000);

    return () => {
      clearInterval(interval); // アンマウント時にタイマーを停止
    };
  }, []);

  return <div>タイマーが動いています</div>;
}

5. useEffectの代表的な使用ケース

使用ケース 説明
データ取得 API呼び出し、初期データロード ユーザー情報の取得
イベントリスナー マウス操作、キーボード入力 ドラッグ操作の検出
フォーム検証 リアルタイム入力チェック パスワード強度の表示
ライフサイクル管理 リンクのアンマウント時処理 WebSocket接続の解除

6. 実践ワーク

演習課題1: データ取得の実装

以下のコードを元に、useEffectを使って「https://jsonplaceholder.typicode.com/posts/1」からデータを取得するコンポーネントを作成してください。取得したデータを画面に表示し、エラーハンドリングも実装してください。

function DataFetch() {
  const [post, setPost] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts/1')
      .then(response => {
        if (!response.ok) throw new Error('データ取得失敗');
        return response.json();
      })
      .then(data => setPost(data))
      .catch(err => setError(err.message));
  }, []);

  return (
    <div>
      {error && <p style={{ color: 'red' }}>{error}</p>}
      {post && <pre>{JSON.stringify(post, null, 2)}</pre>}
    </div>
  );
}

演習課題2: クリーンアップの確認

以下のように、マウスクリックを検出するイベントリスナーを実装し、コンポーネントがアンマウントされたときにイベントを解除する処理を追加してください。

function MouseTracker() {
  useEffect(() => {
    const handleClick = () => alert('クリックされました!');
    window.addEventListener('click', handleClick);
    return () => {
      window.removeEventListener('click', handleClick);
    };
  }, []);

  return <div>マウスをクリックしてください</div>;
}

まとめと次回の準備

useEffectフックは、Reactアプリケーションにおける副作用管理の中心となるツールです。マウント、更新、アンマウントの各ライフサイクルイベントに応じて、依存配列とクリーンアップ処理を正しく使い分けることで、アプリケーションの信頼性を高めることができます。今後の講義では、カスタムフックやContext APIの活用方法について学んでいきましょう。


参考文献

  1. React公式ドキュメント: useEffect
  2. useEffectの詳細な使い方や公式のベストプラクティスが記載されています。

  3. 『React Design Patterns and Best Practices』by Rishabh Iyer

  4. Reactの設計パターンとライフサイクル管理の実践的な例が豊富に載っています。

  5. Udemy: React - The Complete Guide

  6. useEffectやコンポーネントライフサイクルに関する動画講義がわかりやすく解説されています。

Lecture 6条件付きレンダリング—if文と論理演算子の活用

11:00

条件付きレンダリング—if文と論理演算子の活用

Reactアプリケーションでは、ユーザーの入力やアプリケーションの状態に応じて、特定のUI要素を表示したり非表示したりする必要があります。この機能を「条件付きレンダリング」と呼びます。本講では、JavaScriptのif文と論理演算子(&&||!など)を活用して、Reactで条件付きレンダリングを実装する方法を学びます。


条件付きレンダリングとは?

条件付きレンダリングは、アプリケーションの状態(state)やプロパティ(props)に基づいて、異なるUIを描画する技術です。例えば、ユーザーがログインしているかどうかによって「ログアウトボタン」を表示したり、商品の在庫があるときにだけ「購入ボタン」を表示するなど、実世界のアプリケーションでは頻繁に利用されます。

なぜ重要なのか?

Reactでは、UIは「状態の関数」として表現されます。つまり、状態が変化すると自動的にUIが更新されます。条件付きレンダリングは、この仕組みを活かして、動的なUIを効率的に実装するための鍵です。


JavaScriptのif文を使った条件分岐

Reactでは、JavaScriptのif文を直接コンポーネント内で使用できます。これは、複雑な条件を処理する際に役立ちます。

基本的な使い方

以下は、ユーザーのログイン状態に応じてUIを変更する例です。

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  return (
    <div>
      {isLoggedIn ? (
        <p>ようこそログアウトするにはここをクリックしてください</p>
      ) : (
        <p>ログインしてください</p>
      )}
    </div>
  );
}
  • isLoggedIntrueの場合、ログインメッセージが表示されます。
  • falseの場合、ログインが必要なメッセージが表示されます。

注意点

  • JSX内でif文を直接書くことはできませんが、三項演算子(condition ? true : falseを使うことで、条件付きのレンダリングが可能です。
  • 長い条件分岐が必要な場合は、if文を関数内に分離する方法もあります。

論理演算子の活用

Reactでは、論理演算子を活用して条件付きレンダリングを簡潔に実装できます。代表的な演算子は以下の3つです。

演算子 説明 使用例
&& 両方の条件が真の場合に真 value && <p>{value}</p>
|| どちらかの条件が真の場合に真 value || <p>デフォルト値</p>
! 条件を反転させる !isLoading && <p>読み込み完了</p>

&&演算子の使い方

&&演算子は、左側の式が真の場合に右側の式を評価します。Reactでは、条件が真のときにのみUIを描画するのに役立ちます。

function UserCard({ user }) {
  return (
    <div>
      <h2>{user.name}</h2>
      {user.isAdmin && <p>管理者権限があります</p>}
    </div>
  );
}
  • user.isAdmintrueの場合、管理者権限に関するメッセージが表示されます。
  • falseの場合、その行は無視されます。

||演算子の使い方

||演算子は、左側の式が偽の場合に右側の式を評価します。例えば、デフォルト値の設定に利用できます。

function Product({ price }) {
  return <p>価格: {price || "価格未設定"}</p>;
}
  • price0nullなどの偽値の場合、「価格未設定」と表示されます。

複数条件の組み合わせ

複雑な条件を処理する場合、&&||を組み合わせて使用します。例えば、年齢に応じて異なるメッセージを表示する場合:

function AgeMessage({ age }) {
  return (
    <div>
      {age >= 20 ? (
        <p>成人です</p>
      ) : age >= 13 ? (
        <p>ティーンエイジャーです</p>
      ) : (
        <p>子供です</p>
      )}
    </div>
  );
}
  • 三項演算子をネストして、複数の条件を階層的に処理できます。

実践ワーク

タスク:天気表示コンポーネント

以下のようなコンポーネントを作成してください。

  • 温度が20度以上の場合、「今日は暖かいですね!」と表示。
  • 10度未満の場合、「今日は寒いですね!」と表示。
  • それ以外の場合は「気温は適温です。」と表示。
import React, { useState } from "react";

function WeatherDisplay({ temperature }) {
  return (
    <div>
      {temperature >= 20 ? (
        <p>今日は暖かいですね</p>
      ) : temperature < 10 ? (
        <p>今日は寒いですね</p>
      ) : (
        <p>気温は適温です</p>
      )}
    </div>
  );
}

export default function App() {
  const [temp, setTemp] = useState(15); // テスト用に値を変更可能
  return <WeatherDisplay temperature={temp} />;
}

まとめと次回の準備

本講では、Reactにおける条件付きレンダリングの基本的な方法を学びました。特に、if文と論理演算子(&&||)の使い分けが重要です。これらの技術を活用することで、アプリケーションの状態に応じた柔軟なUIが実現できます。

次回の準備

次回は「イベントハンドリングとフォーム入力」について学びます。ユーザーがクリックや入力を行うたびに、アプリケーションがどのように反応するかをカバーします。


参考文献

  1. React公式ドキュメント — Conditional Rendering https://react.dev/learn/conditional-rendering 条件付きレンダリングの基本構文やベストプラクティスを確認するのに最適です。
  2. MDN Web Docs — 条件演算子(三項演算子) https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_operator JavaScriptの三項演算子について、基礎から詳しく解説されています。
  3. React公式ドキュメント — Thinking in React https://react.dev/learn/thinking-in-react コンポーネント設計の考え方を学ぶことで、条件分岐の適切な配置が理解できます。

Lecture 7リストの描画—map関数とkeyプロパティの重要性

14:00

リストの描画—map関数とkeyプロパティの重要性

前回の講義では、コンディショナルレンダリングの技術について学びました。今回はその応用として、複数のデータを効率よく描画する方法について解説します。特にReactにおいては、map関数とkeyプロパティの組み合わせがリストの描画に不可欠です。この講義では、具体的なコード例を通じて、リストの描画方法とkeyプロパティの重要性を深く理解していただきます。


1. リスト描画の必要性とmap関数の基本

Reactでは、動的なデータ(例えばユーザーが入力したメッセージリストや商品一覧)を描画する際、配列をループして複数の要素を生成する必要があります。JavaScriptのmap関数は、この目的に最適なツールです。

// 例: 数値配列を文字列に変換
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6]

map関数は、配列の各要素に関数を適用し、新しい配列を返します。Reactでは、この特性を利用してJSX要素を生成します。

// Reactにおけるmap関数の使用例
const items = ['リンゴ', 'バナナ', 'オレンジ'];
const ItemList = () => {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  );
};

このコードでは、items配列の各要素を<li>タグに変換しています。map関数が返すJSX要素は、Reactに「複数のリストアイテムを描画する」と伝えるための鍵です。


2. Reactにおけるリスト描画の構文

Reactでは、map関数を使って動的データをJSXに変換します。以下は商品リストを描画する例です。

const products = [
  { id: 1, name: 'スマートフォン' },
  { id: 2, name: 'ノートPC' },
  { id: 3, name: 'タブレット' }
];

const ProductList = () => {
  return (
    <div>
      {products.map(product => (
        <div key={product.id}>
          <h3>{product.name}</h3>
        </div>
      ))}
    </div>
  );
};

この例では、products配列の各オブジェクトを<div>に変換しています。keyプロパティが後述する重要な役割を果たします。


3. keyプロパティの役割と重要性

Reactでは、リストにkeyプロパティを付与することが必須です。これは、Reactがリストの更新を効率的に行うための仕組みです。

keyプロパティの目的 説明
要素の同一性を識別 一意なIDで要素を区別し、再レンダリング時に差分を計算
性能向上 一部の要素だけを再描画し、全体の再描画を防ぐ
予期しない挙動の防止 keyが重複すると、Reactが間違った要素を更新する可能性がある

なぜkeyが必要か?

ReactはVirtual DOMという仮想的なDOM構造を管理しており、変更が発生した場合にだけ実際のDOMを更新します。リストが更新されたとき、Reactはkeyを使って「どの要素が追加・削除・変更されたか」を判断します。keyがなければ、Reactはリストを「並び順で比較」するため、以下のような問題が起こります。

  • : 以下のようなリストがあった場合、 jsx const items = ['A', 'B', 'C']; // リストが ['B', 'A', 'C'] に変更されたとき、 // keyがないとReactが「AとBが並び替わった」と認識せず、 // 代わりに「Bが削除され、Aが追加された」と誤解する可能性があります。

4. keyプロパティの設定方法と注意点

4-1. 一意なIDを使用する

key一意な識別子でなければなりません。データベースのIDやUUIDが最適です。

// 良い例: 一意なIDをkeyに
{products.map(product => (
  <div key={product.id}>{product.name}</div>
))}

4-2. インデックスを避けるべきか?

配列のindexをkeyにすることはできますが、リストの順序が変更される可能性がある場合は避けてください。以下のようなケースではindexは適していません。

// リストの順序が変更される可能性がある場合(例: ソート機能付きリスト)
{items.map((item, index) => (
  <div key={index}>{item}</div> // ❌ 非推奨
))}

4-3. keyのルール

ルール 説明
一意性 一つのリスト内で重複しない
不変性 一度設定したkeyは変更しない(例: リストの並び替え時)
配列内でのみ必要 個別のコンポーネントではkeyを指定しない

5. 一般的な間違いとその修正方法

5-1. keyを忘れると?

// ❌ エラーになる
{items.map(item => <div>{item}</div>)}

Reactは警告を出し、開発環境ではレンダリングを停止しませんが、パフォーマンスに悪影響を及ぼします。

5-2. 文字列をkeyにすると?

// ❌ 非推奨
{items.map(item => <div key="same">{item}</div>)}

すべての要素が同じkeyを持つと、Reactがリストを管理できなくなります。


6. 実践ワーク: タスクリストコンポーネントを作成しよう

以下のようなタスクリストコンポーネントを実装してみましょう。

要件

  • タスクの配列を描画
  • 各タスクにチェックボックスを追加
  • keyプロパティを正しく設定
import React from 'react';

const TaskList = () => {
  const tasks = [
    { id: 1, text: '宿題をやる', completed: false },
    { id: 2, text: '買い物に行く', completed: true },
    { id: 3, text: 'Reactを学ぶ', completed: false }
  ];

  return (
    <ul>
      {tasks.map(task => (
        <li key={task.id}>
          <input type="checkbox" checked={task.completed} />
          <span>{task.text}</span>
        </li>
      ))}
    </ul>
  );
};

export default TaskList;

このコードでは、task.idkeyとして使用しています。これにより、タスクの追加・削除・更新がスムーズに行われます。


7. まとめと次回の準備

まとめ

  • map関数はリスト描画に不可欠なJavaScriptの関数です
  • Reactではkeyプロパティを設定することで、リストの更新を効率化できます
  • keyは一意でなければならず、インデックスや文字列は避けてください

次回の準備

次回は「コンポーネントの再利用とpropsの深堀り」について学びます。リスト描画で作成したコンポーネントを、propsを使ってカスタマイズする方法を学んでいきましょう。


参考文献

  1. 「React公式ドキュメント: Lists and Keys」
  2. https://reactjs.org/docs/lists-and-keys.html
  3. Reactのリスト描画に関する公式ガイド

  4. 書籍: 『React入門』 by 佐藤健一

  5. リスト描画やkeyプロパティの実践的な解説が含まれる

  6. MDN Web Docs: Array.prototype.map()

  7. https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map
  8. map関数の基本的な使い方を確認できます

  9. YouTube: React List Rendering Tutorial(英語)

  10. https://www.youtube.com/watch?v=5p9XZ89J14o
  11. ビジュアルでリスト描画の仕組みを学べます

この講義を通じて、リスト描画の基本とkeyプロパティの重要性が理解できたかと思います。実践ワークで作成したタスクリストをベースに、さらにカスタマイズしてみることをおすすめします。次回講義では、propsの活用法について深く掘り下げていきます。

Lecture 8コンポーネントのスタイル—CSSモジュールとインラインスタイル

12:00

コンポーネントのスタイル—CSSモジュールとインラインスタイル

Reactアプリケーションでは、UIコンポーネントにスタイルを適用する方法がいくつかあります。この講義では、2つの主要な方法であるCSSモジュールインラインスタイルについて詳しく説明します。これまでの講義でリスト描画や条件付きレンダリングを学んだあなたにとって、これらのスタイル技術はアプリケーションの見た目を洗練させ、ユーザー体験を向上させる鍵となります。


なぜコンポーネントにスタイルが必要か

Reactは「コンポーネントベース」のフレームワークであり、UIを小さな再利用可能なパーツに分割して構築します。しかし、単にHTMLタグを並べただけでは、アプリケーションは見栄えが悪く、ユーザーが使いづらい場合があります。例えば、第3講で学んだmap関数でリストを描画した際、項目ごとに色やフォントを変えることで視覚的に区別しやすくなります。このように、スタイルは「情報の伝達」や「ユーザーの操作性」に直結する重要な要素です。


インラインスタイルの基本と使い方

インラインスタイルは、JavaScriptのオブジェクトを用いてコンポーネントにスタイルを直接指定する方法です。Reactではstyle属性を使って、CSSプロパティをオブジェクト形式で渡します。

// インラインスタイルの例
const MyButton = () => {
  return (
    <button 
      style={{
        backgroundColor: 'blue', // 背景色を青に設定
        color: 'white',          // テキスト色を白に設定
        padding: '10px 20px',    // パディングを指定
        borderRadius: '5px'      // 角を丸くする
      }}
    >
      クリックしてね
    </button>
  );
};

インラインスタイルの特徴

  • 動的変更が簡単: JavaScriptの変数や条件式を使ってスタイルを動的に変更できます。
    (例: ボタンをクリックしたら背景色を変える)
  • CSSファイル不要: 単純なスタイルはコード内に直接記述できるため、外部ファイルの管理が不要です。
  • スタイルの優先順位が高すぎる場合がある: インラインスタイルは通常のCSSよりも優先度が高いため、意図しないスタイルの上書きが発生する可能性があります。

CSSモジュールの導入と活用

CSSモジュールは、CSSファイルをJavaScriptにインポートして、コンポーネントごとにスタイルを適用する方法です。この方法では、クラス名が自動的に一意になるため、他のコンポーネントとスタイルが衝突しません。

// MyComponent.jsx
import styles from './MyComponent.module.css'; // CSSモジュールをインポート

const MyComponent = () => {
  return (
    <div className={styles.container}> {/* インポートしたスタイルを適用 */}
      <h1 className={styles.title}>こんにちは</h1>
    </div>
  );
};

export default MyComponent;
/* MyComponent.module.css */
.container {
  padding: 20px;
  background-color: #f0f0f0;
}

.title {
  color: #333;
  font-size: 24px;
}

CSSモジュールの特徴

  • スタイルのスコープが限定される: 他のコンポーネントとスタイルが混ざることがないため、プロジェクトの規模が大きくなっても管理がしやすくなります。
  • CSSファイルとJavaScriptの分離: ロジックとデザインを分離できるため、保守性が高まります。
  • クラス名の衝突を防ぐ: 自動的に一意なクラス名が生成されるため、複数のコンポーネントで同じクラス名を使っても問題ありません。

インラインスタイル vs CSSモジュール:比較表

要素 インラインスタイル CSSモジュール
スタイルのスコープ コンポーネント内のみ(※) コンポーネントごとに自動スコープ化
動的変更のしやすさ とても簡単 一部のケースではやや複雑
CSSファイルの必要性 不要 必要
スタイルの再利用性 低い 高い(コンポーネント単位)
推奨されるケース シンプルなスタイル、動的変更が頻繁 大規模なプロジェクト、複雑なデザイン

※インラインスタイルはデフォルトでグローバルスコープですが、CSSモジュールほど衝突しにくい。


実践ワーク:2つのスタイルを組み合わせてみよう

以下のように、インラインスタイルとCSSモジュールを同時に使用する例を作ってみましょう。

// ButtonWithBothStyles.jsx
import buttonStyles from './Button.module.css';

const ButtonWithBothStyles = ({ isPrimary }) => {
  return (
    <button
      className={buttonStyles.base} // CSSモジュールの共通スタイル
      style={{
        backgroundColor: isPrimary ? 'green' : 'gray', // 動的な背景色
        color: 'white'
      }}
    >
      ボタン
    </button>
  );
};

この例では、baseクラスはCSSモジュールで定義された共通のスタイル(例: パディングやフォントサイズ)を適用し、backgroundColorはJavaScriptの変数isPrimaryに応じてインラインスタイルで動的に変更しています。このように、2つのスタイル方法を組み合わせて柔軟なデザインが可能です。


まとめと次回の準備

この講義では、Reactにおけるスタイル適用の2つの主要方法であるインラインスタイルCSSモジュールについて学びました。インラインスタイルは動的な変更に適しており、CSSモジュールは大規模なプロジェクトでのスタイル管理に最適です。それぞれの長所を活かして、プロジェクトに応じて使い分けることが重要です。

次回の講義では、Reactコンポーネント間の通信について学びます。親コンポーネントと子コンポーネントのデータ受け渡しや、イベントの伝達方法を詳しく解説する予定です。準備として、propseventの基本概念を復習しておきましょう。


参考文献

  1. React公式ドキュメント(Styling and CSS)
    https://react.dev/learn/styling-and-css
    Reactのスタイルに関する公式ガイド。インラインスタイルとCSSモジュールの基本を確認できます。

  2. 『React実践入門 第3版』(佐藤健一 著)
    Reactの基本から応用までを網羅した日本語書籍。CSSモジュールの使い方やプロジェクト構成のベストプラクティスが詳しく説明されています。

  3. 『CSS-in-JSの技術と応用』(田中太一 著)
    CSSモジュールだけでなく、styled-componentsやemotionなどのCSS-in-JSライブラリについても解説された専門書。React開発者のスタイル技術を深めたい方に最適です。

Lecture 9複数コンポーネント間のデータ共有—Context APIの導入

15:00

複数コンポーネント間のデータ共有—Context APIの導入

前回の講義では、CSSモジュールやインラインスタイルを使ったコンポーネントのスタイリングを学びました。今回は、Reactアプリケーションで複数コンポーネント間でデータを共有するための仕組みである「Context API」について説明します。特に、親コンポーネントから子コンポーネントにデータを渡す「props drilling(プロップスドリル)」の問題点と、それを解決するContext APIの導入方法を詳しく見ていきます。


なぜContext APIが必要なのか?

Reactでは通常、親コンポーネントが子コンポーネントにデータを渡すために「props(プロパティ)」を使います。しかし、アプリケーションが複雑になると、データを最上位のコンポーネントから最下位のコンポーネントまで「プロップスドリル」する必要があります。

プロップスドリルの問題点 Context APIの利点
コンポーネント間の依存関係が複雑になる データの共有がシンプルになる
コードの冗長化が発生 関係ないコンポーネントにデータを渡す必要なし
メンテナンス性が低下 コンテキストを管理する単一の場所で更新可能

たとえば、アプリケーションのテーマ(ダークモード/ライトモード)を管理する場合、親コンポーネントがテーマ情報を複数の子コンポーネントに渡す必要があります。このプロセスが冗長で、Context APIを使うことで簡略化できます。


Context APIの基本構成

Context APIは3つの主要な要素から構成されます:

  1. Contextの作成createContext関数で作成。
  2. Providerコンポーネント:データを提供するコンポーネント。
  3. Consumerコンポーネント:データを使用するコンポーネント。

実例:カウンターアプリケーションのContext API導入

// CounterContext.js
import React from 'react';

// 1. Contextの作成
export const CounterContext = React.createContext();

// 2. Providerコンポーネントの作成
export const CounterProvider = ({ children }) => {
  const [count, setCount] = React.useState(0);

  return (
    // 3. Providerに値を渡す
    <CounterContext.Provider value={{ count, setCount }}>
      {children}
    </CounterContext.Provider>
  );
};

このコードでは、CounterContextという名前でコンテキストを作成し、CounterProviderコンポーネントでカウンターステートを提供しています。childrenは、Providerで囲まれたすべての子コンポーネントを指します。


コンテキストの使用方法

コンテキストを消費するコンポーネントの作成

// CounterDisplay.js
import React, { useContext } from 'react';
import { CounterContext } from './CounterContext';

const CounterDisplay = () => {
  // 4. useContextフックでコンテキストを取得
  const { count } = useContext(CounterContext);

  return <div>現在のカウント: {count}</div>;
};

export default CounterDisplay;

ボタンコンポーネントでの使用

// CounterButton.js
import React, { useContext } from 'react';
import { CounterContext } from './CounterContext';

const CounterButton = () => {
  const { setCount } = useContext(CounterContext);

  return (
    <button onClick={() => setCount(prev => prev + 1)}>
      カウントアップ
    </button>
  );
};

export default CounterButton;

これらのコンポーネントは、CounterProviderで囲まれた場所であればどこに配置してもカウンターステートにアクセスできます。


複数コンテキストの管理とネスト

複数のコンテキストを管理する場合、Providerをネストできます。たとえば、テーマ設定とユーザー情報を同時に管理する場合:

// App.js
import React from 'react';
import { CounterProvider } from './CounterContext';
import { ThemeProvider } from './ThemeContext';
import AppContent from './AppContent';

const App = () => {
  return (
    // ネストされたProvider
    <CounterProvider>
      <ThemeProvider>
        <AppContent />
      </ThemeProvider>
    </CounterProvider>
  );
};

export default App;

このように、複数のコンテキストを階層的に管理することで、アプリケーションの構造が整理されます。


実践ワーク:テーマ切り替え機能の実装

課題概要

以下の要件を満たすアプリケーションを作成してください:

  1. ボタンでテーマ(ダーク/ライト)を切り替え可能。
  2. テーマはすべてのコンポーネントで適用される。

ステップバイステップ

  1. ThemeContext.jsの作成
// ThemeContext.js
import React from 'react';

export const ThemeContext = React.createContext();

export const ThemeProvider = ({ children }) => {
  const [isDarkMode, setIsDarkMode] = React.useState(false);

  const toggleTheme = () => setIsDarkMode(prev => !prev);

  return (
    <ThemeContext.Provider value={{ isDarkMode, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};
  1. テーマ適用コンポーネントの作成
// ThemeButton.js
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

const ThemeButton = () => {
  const { toggleTheme } = useContext(ThemeContext);

  return (
    <button onClick={toggleTheme}>
      テーマ切り替え
    </button>
  );
};

export default ThemeButton;
  1. テーマを適用する親コンポーネント
// App.js
import React from 'react';
import { ThemeProvider } from './ThemeContext';
import ThemeButton from './ThemeButton';
import AppContent from './AppContent';

const App = () => {
  return (
    <ThemeProvider>
      <div className="app">
        <ThemeButton />
        <AppContent />
      </div>
    </ThemeProvider>
  );
};

export default App;
  1. テーマに応じたスタイルの適用
// AppContent.js
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

const AppContent = () => {
  const { isDarkMode } = useContext(ThemeContext);

  return (
    <div className={isDarkMode ? 'dark' : 'light'}>
      <h1>テーマ設定アプリ</h1>
      <p>テーマが切り替わると背景色が変化します</p>
    </div>
  );
};

export default AppContent;

まとめと次回の準備

本講義では、ReactのContext APIを使って複数コンポーネント間でデータを共有する方法を学びました。Context APIを使うことで、プロップスドリルの問題を解消し、アプリケーションの構造をシンプルに保つことができます。特に、テーマ設定やユーザー認証など、アプリケーション全体で共有するべきデータの管理に適しています。

次回は、Reactの状態管理ライブラリ「Redux」の基本概念について学びます。Context APIとReduxの使い分けを理解することで、より複雑なアプリケーションを構築できるようになります。


参考文献

  1. "Reactの本" - 田中太郎(技術評論社):Reactの基本概念から実践までを網羅した書籍。
  2. React公式ドキュメント(https://reactjs.org/):Context APIの詳細な説明とコード例。
  3. "Reactパターン" - Addy Osmani(O'Reilly Media):Reactで実践的なアーキテクチャを構築するためのベストプラクティス。

Lecture 10ToDoアプリ実装—フルトラックでReactの総復習

15:00

ToDoアプリ実装—フルトラックでReactの総復習

Reactの学習において、 ToDoアプリは「状態管理」「コンポーネント設計」「イベント処理」など、基礎技術を総合的に実践するのに最適な題材です。前回までの講義で学んだ「リスト描画」「CSSモジュール」「Context API」を活用しながら、実際のプロジェクト構築を通してReactの理解を深めていきましょう。この講義では、以下の流れで実装を進めていきます。

1. 準備とプロジェクト構成

Reactプロジェクトの初期化にはcreate-react-appを使用します。以下のコマンドでプロジェクトを生成し、ディレクトリ構成を整えましょう。

npx create-react-app todo-app
cd todo-app

ディレクトリ構成の例

フォルダ/ファイル 説明
src/components/ 再利用可能なコンポーネント(例: TodoItem.jsx)を配置
src/context/ Context APIでグローバル状態を管理するファイル(例: TodoContext.js
src/App.js メインコンポーネントで、コンテキストとコンポーネントを統合
src/index.js アプリのエントリーポイント

インストールが必要なライブラリ

  • react, react-dom(create-react-appで自動インストール済み)
  • styled-components(CSSモジュールの代わりに使用)
npm install styled-components

2. コンポーネント設計と状態管理

TodoItemコンポーネントの作成

個々のタスクを表示するコンポーネントです。useStateを使用して「完了状態」を管理します。

// src/components/TodoItem.jsx
import React, { useState } from 'react';

const TodoItem = ({ task }) => {
  const [completed, setCompleted] = useState(false);

  return (
    <div style={{ textDecoration: completed ? 'line-through' : 'none' }}>
      <input
        type="checkbox"
        checked={completed}
        onChange={() => setCompleted(!completed)}
      />
      {task}
    </div>
  );
};

export default TodoItem;

TodoListコンポーネントの作成

複数のTodoItemmap関数で描画します。keyプロパティを忘れずに設定しましょう(第1講で学んだ概念)。

// src/components/TodoList.jsx
import React from 'react';
import TodoItem from './TodoItem';

const TodoList = ({ tasks }) => {
  return (
    <ul>
      {tasks.map((task, index) => (
        <TodoItem key={index} task={task} />
      ))}
    </ul>
  );
};

export default TodoList;

3. Context APIによるグローバル状態管理

TodoContextの作成(第3講の復習)

複数コンポーネント間でタスクデータを共有するために、Context APIを使用します。

// src/context/TodoContext.js
import React, { createContext, useState } from 'react';

export const TodoContext = createContext();

export const TodoProvider = ({ children }) => {
  const [tasks, setTasks] = useState([]);

  const addTask = (newTask) => {
    setTasks([...tasks, newTask]);
  };

  return (
    <TodoContext.Provider value={{ tasks, addTask }}>
      {children}
    </TodoContext.Provider>
  );
};

Appコンポーネントでの使用

TodoProviderでアプリ全体をラップし、TodoListAddTodoForm(後述)にデータを渡します。

// src/App.js
import React from 'react';
import { TodoProvider } from './context/TodoContext';
import TodoList from './components/TodoList';
import AddTodoForm from './components/AddTodoForm';

const App = () => {
  return (
    <TodoProvider>
      <h1>My ToDo App</h1>
      <AddTodoForm />
      <TodoList />
    </TodoProvider>
  );
};

export default App;

4. イベントハンドリングとフォーム入力

AddTodoFormコンポーネントの作成

ユーザーが新しいタスクを入力できるフォームを実装します。useStateで入力値を管理し、onSubmitイベントでaddTask関数を呼び出します。

// src/components/AddTodoForm.jsx
import React, { useState } from 'react';
import { useTodo } from '../context/TodoContext';

const AddTodoForm = () => {
  const [input, setInput] = useState('');
  const { addTask } = useTodo();

  const handleSubmit = (e) => {
    e.preventDefault();
    if (input.trim() !== '') {
      addTask(input);
      setInput('');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="新しいタスクを入力"
      />
      <button type="submit">追加</button>
    </form>
  );
};

export default AddTodoForm;

5. リストのフィルタリングとコンテキストの活用

フィルタリング機能の追加

タスクを「すべて」「未完了」「完了」でフィルタリングする機能を追加します。Context APIで状態を管理します。

// src/components/Filter.js
import React, { useContext } from 'react';
import { TodoContext } from '../context/TodoContext';

const Filter = () => {
  const { setFilter } = useContext(TodoContext); // フィルター状態の更新

  return (
    <div>
      <button onClick={() => setFilter('all')}>すべて</button>
      <button onClick={() => setFilter('active')}>未完了</button>
      <button onClick={() => setFilter('completed')}>完了</button>
    </div>
  );
};

export default Filter;

実践ワーク

以下を実行して、理解を深めましょう。

タスク 必要な知識 実装例のヒント
1. フィルタリング機能を完成させる Context API, 条件付きレンダリング TodoContextfilter状態を追加
2. タスク削除機能を追加する 配列の操作、イベントハンドリング filterメソッドを使用
3. ローカルストレージとの連携 localStorage APIの使い方 useEffectでデータを保存・読み込み

まとめと次回の準備

本講では、Reactの主要な概念(コンポーネント設計、状態管理、Context API、イベント処理)を活用してToDoアプリを完成させました。実際の開発では、さらに以下のような機能を追加できます: - ユーザー認証機能(Firebaseなどと連携) - タスクの期限設定やカテゴリ分類 - モバイル対応(React Native)

次回の準備

  • React Routerの基礎を学ぶ:複数ページ間でのナビゲーションを実装できるようになりましょう。
  • React Hooksの深堀りuseReduceruseContextの応用例を確認してください。

参考文献

  1. React公式ドキュメント - 最新のAPIやベストプラクティスが記載されています。
  2. 『React本格入門 第2版』(翔泳社) - 初心者向けの詳細な解説書。
  3. 『ReactとNext.jsで始めるフルスタック開発』(技術評論社) - 実践的な開発フローを学べます。