4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React入門(初心者向け)

Posted at

React入門(目次)

React初心者向けコース

1. Reactの基礎

1.1 はじめに

  • Reactとは何か、なぜReactを学ぶのか
  • シングルページアプリケーション(SPA)の基本
  • Reactの歴史と現代Web開発での役割

1.2 環境構築

  • Node.jsとnpmのインストール
  • Create React Appを使ってReactプロジェクトを作成する
  • 開発ツール(VSCode、ブラウザのReact DevTools)

1.3 JSXの基本

  • JSXとは何か
  • JSXの書き方とルール
  • HTMLとの違い

1.4 コンポーネントの基本

  • 関数コンポーネント vs クラスコンポーネント
  • コンポーネントの作成と組み合わせ
  • コンポーネントの再利用性

2. Reactの核心機能

2.1 Props(プロパティ)の理解

  • Propsの役割
  • コンポーネント間のデータの受け渡し
  • Propsを使ったコンポーネントの作成

2.2 State(状態)の管理

  • Stateの役割と使い方
  • 状態管理とコンポーネントの再レンダリング
  • 状態を使って簡単なインタラクティブなアプリを作成

2.3 イベント処理

  • ユーザーイベント(クリック、入力、フォーム送信)の処理
  • イベントハンドラーの作成
  • イベントを活用したアプリの作成

3. Reactの実践

3.1 リストとキー

  • リストをレンダリングする方法
  • リストをレンダリングする際のキーの重要性

3.2 条件付きレンダリング

  • 条件に基づいてコンポーネントを表示/非表示にする
  • if文や三項演算子を使ったレンダリング

3.3 フォームの作成と制御

  • フォーム要素の制御と非制御
  • フォームデータの処理と状態管理

3.4 APIとの連携(データフェッチング)

  • fetchaxios を使って外部APIからデータを取得
  • 非同期処理(Promise、async/await)の基本
  • 取得したデータを表示する

4. 高度なトピック

4.1 useEffectフック

  • useEffectの基礎
  • 副作用の管理とライフサイクル
  • データのフェッチングやDOM操作

4.2 useStateフックの応用

  • 複雑な状態の管理
  • オブジェクトや配列の状態更新

4.3 React Routerによるルーティング

  • シングルページアプリケーション(SPA)のルーティング
  • React Routerのセットアップと使い方
  • ページ間の移動とパラメータの扱い

4.4 コンテキストAPI

  • グローバルな状態管理の必要性
  • React Context APIの使い方
  • Propsドリリングを解消する方法

5. プロジェクト演習

5.1 ToDoリストアプリの作成

  • フォームの入力と状態管理
  • リストの表示、追加、削除
  • 状態とイベント処理を総合的に学ぶ

5.2 簡単なメモアプリの作成

  • ローカルストレージを使ったデータの保存
  • カスタムフックの作成
  • コンポーネントのリファクタリング

6. 最終プロジェクト:ポートフォリオサイトの作成

  • Reactの基本機能を活用して、個人のポートフォリオサイトを作成
  • 自己紹介、プロジェクトリスト、フォームを含むページ構成
  • 状態管理やコンポーネントの構成を強化

学習時間

  • このコースは全体で4〜6週間を目安とし、各セッションは2〜3時間程度で進めることを推奨します。

学習目標

  • Reactの基本概念を理解し、小規模なアプリケーションを自分で作成できるようになる。
  • 実際の開発に必要なツールや技術を習得し、より高度なReactアプリケーションを作成できる基礎を身につける。

サポート教材

  • 実習ベースのコードサンプル
  • 課題プロジェクト
  • リファレンス資料と動画リンク

このコースは、初心者がReactの基礎をしっかり理解し、実践的なスキルを身につけることを目指しています。

1. Reactの基礎

1.1 Reactとは何か、なぜReactを学ぶのか

Reactとは?

Reactは、Facebookによって開発された、ユーザーインターフェース(UI)を作成するためのJavaScriptライブラリです。通常、Webページの更新には全ページをリロードする必要がありましたが、Reactを使うとページの一部分だけを更新できます。これにより、ユーザーがより快適にアプリケーションを利用できるようになります。

Reactの特徴は、Webページを**「コンポーネント」**という小さな部品に分け、それぞれを管理できる点です。これにより、複雑なUIでも効率的に開発が可能になります。


なぜReactを学ぶのか?

  • 再利用可能なコンポーネント:

    Reactでは、同じUIの部分を複数のページや場所で使いたい場合に、コンポーネントを作成して再利用できます。これにより、開発時間の短縮や保守性の向上が期待できます。

  • 高速なレンダリング:

    ページ全体をリロードせずに必要な部分だけ更新するので、ページの動作がスムーズになります。これを可能にするのがReactの仮想DOMです。

  • シングルページアプリケーション(SPA)向け:

    ReactはSPAを作成するのに非常に適しています。SPAは、ユーザーがページを移動する際に全ページを再読み込みする代わりに、JavaScriptで必要な部分だけを更新します。


シングルページアプリケーション(SPA)とは?

通常のWebサイトでは、ユーザーがリンクをクリックすると、新しいページに移動するたびにサーバーからそのページ全体をロードします。しかし、これだとページの読み込みが遅くなります。

  • *SPA(Single Page Application)**では、最初に1ページ分のHTML・CSS・JavaScriptを読み込み、その後ページ遷移が必要な場合でも必要なデータだけをサーバーから取得して、画面の一部だけを動的に更新します。これにより、ユーザーの操作に対してレスポンスが速くなります。

Reactのコード例:シンプルなSPA

次に、Reactを使った簡単なSPAの例を見てみましょう。

javascript
コードをコピーする
import React, { useState } from 'react';

function App() {
  const [page, setPage] = useState('home');

  return (
    <div>
      <nav>
        <button onClick={() => setPage('home')}>ホーム</button>
        <button onClick={() => setPage('about')}>アバウト</button>
      </nav>
      <div>
        {page === 'home' && <HomePage />}
        {page === 'about' && <AboutPage />}
      </div>
    </div>
  );
}

function HomePage() {
  return <h1>ホームページへようこそ!</h1>;
}

function AboutPage() {
  return <h1>このアプリについて</h1>;
}

export default App;

説明:

  • このコードは、ホームページとアバウトページを切り替える、シンプルなシングルページアプリケーション(SPA)です。
  • useStateフックを使って、現在のページを管理しています。setPageでページを切り替えることができます。
  • pageの値が'home'なら<HomePage />が表示され、'about'なら<AboutPage />が表示されます。これにより、ページ遷移が実現されていますが、実際にはページ全体のリロードは行われません。

Reactの歴史と現代Web開発での役割

Reactは2013年にFacebookによって開発され、公開されました。当時は、WebアプリケーションのUIが複雑化していたため、効率的にUIを管理できる新しいライブラリが求められていました。Reactの登場により、次のような変化が起こりました。

  • 宣言的UI:

    従来の命令型プログラミングとは異なり、Reactは「どのようにUIを作るか」ではなく「どのようなUIになるべきか」を宣言的に記述できます。これにより、コードがシンプルでわかりやすくなります。

  • コンポーネントベース:

    Reactのコンポーネントは、Web開発の部品を再利用可能な形で分割し、チームでの開発や大規模アプリケーションでの保守をしやすくしました。


まとめ

  • Reactは、コンポーネントを使ってWebアプリケーションのUIを効率よく作成するためのライブラリです。
  • SPAは、ユーザーの操作に対してページ全体をリロードせずに動的に更新できるWebアプリの一種です。
  • Reactの強みは、コンポーネントの再利用性や高速なレンダリングです。

1.2 環境構築

Reactを使ってアプリを作るには、まず開発環境を整える必要があります。このセクションでは、Reactを始めるために必要なツールをインストールし、簡単なプロジェクトを作成する方法を説明します。


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

Reactプロジェクトを作成するためには、まずNode.jsとそのパッケージマネージャである**npm(Node Package Manager)**をインストールします。これらを使ってReact関連のツールをインストールし、プロジェクトを管理します。

手順:

  1. Node.jsのダウンロードとインストール

    • 公式サイト Node.js にアクセスし、最新の推奨版をダウンロードします。
    • ダウンロードが完了したら、インストーラーの指示に従ってインストールします。
  2. Node.jsとnpmのバージョン確認

    • インストールが完了したら、ターミナル(WindowsならコマンドプロンプトやPowerShell、MacならTerminal)を開いて、以下のコマンドを入力して、Node.jsとnpmが正しくインストールされているか確認します。
    bash
    コードをコピーする
    node -v
    npm -v
    
    
    • node -v ではNode.jsのバージョン、npm -v ではnpmのバージョンが表示されます。これで、Node.jsとnpmのインストールが完了です。

2. Create React Appを使ってReactプロジェクトを作成する

Reactの公式ツールであるCreate React Appを使うことで、簡単にReactプロジェクトをセットアップできます。これにより、面倒な設定なしで、React開発に必要なファイルや設定が自動で作成されます。

手順:

  1. 新しいReactアプリを作成
    ターミナルで、以下のコマンドを実行して、新しいReactプロジェクトを作成します。

    bash
    コードをコピーする
    npx create-react-app my-react-app
    
    
    • npx create-react-app my-react-appmy-react-appは、プロジェクトの名前です。好きな名前に変更できます。
  2. プロジェクトディレクトリに移動
    プロジェクトの作成が完了したら、以下のコマンドでそのディレクトリに移動します。

    bash
    コードをコピーする
    cd my-react-app
    
    
  3. Reactアプリを起動
    次に、以下のコマンドを実行して開発サーバーを起動します。

    bash
    コードをコピーする
    npm start
    
    
    • このコマンドを実行すると、ブラウザが自動で開き、Reactアプリが表示されます。URLは通常、http://localhost:3000 です。

初期状態のReactアプリ

Create React Appを使って作成されたアプリの初期状態は、シンプルな1ページのWebアプリです。ページには「Edit src/App.js and save to reload.」というメッセージが表示されているはずです。このファイルを編集することで、アプリの内容を変更できます。


3. 開発ツール

Reactを効率よく開発するためには、いくつかの便利な開発ツールがあります。ここでは、よく使われるツールを紹介します。

1. VSCode(Visual Studio Code)

VSCodeは、人気のある無料のコードエディタで、React開発に非常に適しています。

  1. ダウンロードとインストール

  2. VSCodeでプロジェクトを開く

    • ターミナルでmy-react-appディレクトリに移動している状態で、以下のコマンドを実行してVSCodeでプロジェクトを開きます。
    bash
    コードをコピーする
    code .
    
    
    • このコマンドを実行すると、VSCodeが開き、プロジェクトフォルダが表示されます。
  3. おすすめの拡張機能
    React開発に役立つVSCodeの拡張機能をいくつかインストールしましょう。

    • ES7+ React/Redux/React-Native snippets: よく使うReactのコードスニペット(コードのショートカット)を簡単に書けるようになります。
    • Prettier: コードフォーマッター。コードの書き方を自動で整えてくれます。

2. React DevTools

Reactには、ブラウザでReactのコンポーネントの状態や構造を確認できる便利なツール「React Developer Tools」があります。

  1. React DevToolsのインストール
    • ChromeやFirefoxの拡張機能としてインストールできます。以下のリンクからインストールします。
  2. 使用方法
    • React DevToolsをインストールした後、Reactアプリを開いた状態で、ブラウザの開発者ツール(F12または右クリックして「検証」)に新しい「React」タブが追加されています。
    • これを使うと、アプリ内のコンポーネントのツリー構造や、各コンポーネントの状態(state)やプロパティ(props)を確認できます。

まとめ

  • Node.jsとnpmをインストールし、Reactの環境を整えます。
  • Create React Appを使って、新しいReactプロジェクトを簡単にセットアップできます。
  • 開発には、VSCodeなどのエディタや、React DevToolsのようなブラウザツールを使うと便利です。

1.3 JSXの基本

JSXとは何か

  • *JSX(JavaScript XML)**は、Reactで使用される構文の一種で、JavaScriptの中にHTMLのような記述を埋め込むことができます。これにより、UIを直感的に記述できるようになります。JSXを使うと、コンポーネントの構造を視覚的に理解しやすくなり、コードがシンプルに保たれます。

例えば、以下のようなJSXのコードがあります。

javascript
コードをコピーする
const element = <h1>Hello, world!</h1>;

このコードは、<h1>タグの中に「Hello, world!」というテキストを表示する要素を定義しています。JSXはJavaScriptと一緒に使えるため、変数や関数を簡単に組み合わせることができます。


JSXの書き方とルール

JSXを使う際には、いくつかの書き方やルールがあります。以下に基本的なルールを紹介します。

  1. タグは必ず閉じる

    • JSXでは、HTMLと同じようにタグは必ず閉じる必要があります。
    javascript
    コードをコピーする
    // 正しい
    const element = <div>Hello</div>;
    
    // 間違い
    const element = <div>Hello</; // エラーになる
    
    
  2. クラス名はclassNameを使用

    • JSXでは、HTMLのclass属性はclassNameとして記述します。これはJavaScriptの予約語であるclassと衝突しないためです。
    javascript
    コードをコピーする
    const element = <div className="container">コンテナ</div>;
    
    
  3. JavaScript式を埋め込む

    • {}を使って、JSX内にJavaScriptの式を埋め込むことができます。
    javascript
    コードをコピーする
    const name = "太郎";
    const element = <h1>こんにちは、{name}さん!</h1>;
    
    
  4. スタイルの指定

    • JSXでは、インラインスタイルをオブジェクトとして指定します。この場合、CSSのプロパティはキャメルケースで記述します。
    javascript
    コードをコピーする
    const element = (
      <div style={{ backgroundColor: 'blue', color: 'white' }}>
        スタイル付きのコンテナ
      </div>
    );
    
    

HTMLとの違い

JSXとHTMLには似ている部分が多いですが、いくつかの重要な違いもあります。

  1. 属性名

    • JSXでは、HTMLの属性名が異なる場合があります。例えば、classclassNameforhtmlForに変更されます。
    javascript
    コードをコピーする
    // HTML
    <label for="name">名前</label>
    
    // JSX
    <label htmlFor="name">名前</label>
    
    
  2. タグの閉じ方

    • JSXでは、空のタグは自己完結型で書く必要があります。例えば、<img>タグは<img />と書きます。
    javascript
    コードをコピーする
    // HTML
    <img src="image.png">
    
    // JSX
    <img src="image.png" />
    
    
  3. 式の埋め込み

    • JSXでは、HTMLでは直接記述できないJavaScriptの式を {} を使って埋め込むことができます。
    javascript
    コードをコピーする
    const count = 5;
    const element = <h1>カウント: {count}</h1>;
    
    
  4. JavaScriptの予約語

    • JSXでは、JavaScriptの予約語に対して特別な名前を使います。例えば、classclassNameforhtmlForとします。

まとめ

  • JSXは、JavaScript内でHTMLのような構文を使ってUIを記述するための構文です。
  • JSXの書き方には、タグの閉じ方や属性名の違い、JavaScript式の埋め込みなどのルールがあります。
  • JSXとHTMLには共通点が多いものの、いくつかの重要な違いが存在します。これらを理解して、Reactの開発に役立てましょう。

1.4 コンポーネントの基本

Reactの心臓部はコンポーネントです。コンポーネントを使うことで、UIを小さな部品に分割し、管理しやすくします。このセクションでは、コンポーネントの基本について説明します。


1. 関数コンポーネント vs クラスコンポーネント

Reactには主に2種類のコンポーネントがあります。

  1. 関数コンポーネント

    • シンプルで、状態を持たないコンポーネントを作るのに使います。
    • Reactのフック(Hooks)を使用することで、状態を持たせることもできます。
    javascript
    コードをコピーする
    function Greeting(props) {
      return <h1>こんにちは、{props.name}さん!</h1>;
    }
    
    // 使用例
    const App = () => {
      return <Greeting name="太郎" />;
    };
    
    
  2. クラスコンポーネント

    • より複雑なロジックや状態を持つコンポーネントを作るために使います。
    • React.Componentを継承し、renderメソッドでUIを定義します。
    javascript
    コードをコピーする
    class Greeting extends React.Component {
      render() {
        return <h1>こんにちは、{this.props.name}さん!</h1>;
      }
    }
    
    // 使用例
    const App = () => {
      return <Greeting name="太郎" />;
    };
    
    

まとめ:

  • 関数コンポーネントは簡潔で軽量なため、最近のReact開発では主に使われます。
  • クラスコンポーネントは状態管理やライフサイクルメソッドを持つため、複雑なアプリケーションで使われることがありますが、関数コンポーネントの使用が推奨される傾向にあります。

2. コンポーネントの作成と組み合わせ

Reactでは、コンポーネントを作成して、他のコンポーネント内で組み合わせることができます。これにより、アプリケーションの構造をシンプルに保ちながら、再利用可能な部品を作成できます。

コンポーネントの例

javascript
コードをコピーする
function Header() {
  return <header><h1>私のアプリ</h1></header>;
}

function Footer() {
  return <footer><p>© 2024 私のアプリ</p></footer>;
}

function MainContent() {
  return (
    <main>
      <p>ここがメインコンテンツです。</p>
    </main>
  );
}

function App() {
  return (
    <div>
      <Header />
      <MainContent />
      <Footer />
    </div>
  );
}

説明:

  • HeaderFooterMainContentの3つの関数コンポーネントを作成し、Appコンポーネント内でそれらを組み合わせています。
  • これにより、アプリ全体のレイアウトを構成することができます。

3. コンポーネントの再利用性

コンポーネントは、再利用性が高いのが特徴です。1度作成したコンポーネントは、異なる場所で何度でも使うことができます。これにより、コードの重複を減らし、メンテナンス性を向上させることができます。

再利用性の例

javascript
コードをコピーする
function Button(props) {
  return <button style={{ backgroundColor: props.color }}>{props.label}</button>;
}

function App() {
  return (
    <div>
      <h1>ボタンの例</h1>
      <Button color="blue" label="青いボタン" />
      <Button color="red" label="赤いボタン" />
      <Button color="green" label="緑のボタン" />
    </div>
  );
}

説明:

  • Buttonコンポーネントを作成し、colorlabelをプロパティ(props)として受け取ります。
  • Appコンポーネント内で、異なる色とラベルを持つボタンを複数作成しています。
  • これにより、Buttonコンポーネントを1つ作成するだけで、異なる見た目のボタンを簡単に生成できます。

まとめ

  • 関数コンポーネントクラスコンポーネントの違いを理解し、基本的なコンポーネントを作成する方法を学びました。
  • コンポーネントを組み合わせて、アプリケーションのレイアウトを構築する方法を学びました。
  • コンポーネントの再利用性を活かすことで、コードを効率よく管理し、メンテナンスを容易にすることができます。これがReactの強力な特徴の一つです。

2. Reactの核心機能

2.1 Props(プロパティ)の理解

  • *Props(プロパティ)**は、Reactコンポーネントにデータを渡すための仕組みです。Propsを使うことで、コンポーネント間でデータを受け渡しし、より動的で再利用可能なコンポーネントを作成することができます。

1. Propsの役割

Propsは、親コンポーネントから子コンポーネントにデータや設定を渡すための手段です。これにより、コンポーネントは与えられたデータに基づいて異なる表示や動作を行います。

  • : ボタンコンポーネントにラベルや色を渡す場合
javascript
コードをコピーする
function Button(props) {
  return <button style={{ backgroundColor: props.color }}>{props.label}</button>;
}

ここでは、Buttonコンポーネントがcolorlabelというプロパティを受け取っています。これにより、ボタンの見た目や表示内容を柔軟に変更できます。


2. コンポーネント間のデータの受け渡し

Propsを使用することで、親コンポーネントから子コンポーネントにデータを渡すことができます。以下に、その具体例を示します。

javascript
コードをコピーする
function Greeting(props) {
  return <h1>こんにちは、{props.name}さん!</h1>;
}

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

説明:

  • AppコンポーネントがGreetingコンポーネントを使用しています。
  • AppからGreetingnameプロパティを渡し、Greetingはその値を使って挨拶を表示します。

3. Propsを使ったコンポーネントの作成

Propsを使うことで、より汎用的で再利用可能なコンポーネントを作成することができます。以下は、複数の異なるメッセージを表示できるMessageコンポーネントの例です。

javascript
コードをコピーする
function Message(props) {
  return (
    <div>
      <h2>{props.title}</h2>
      <p>{props.content}</p>
    </div>
  );
}

function App() {
  return (
    <div>
      <Message title="お知らせ" content="明日の会議は中止になりました。" />
      <Message title="注意" content="今週末の天気にご注意ください。" />
      <Message title="お礼" content="参加していただきありがとうございました。" />
    </div>
  );
}

説明:

  • Messageコンポーネントは、titlecontentというプロパティを受け取ります。
  • Appコンポーネントから異なるデータを渡すことで、異なるメッセージを表示しています。
  • これにより、Messageコンポーネントは、異なる内容で何度でも使用できる汎用性を持っています。

まとめ

  • Propsは、親コンポーネントから子コンポーネントにデータを渡すための仕組みです。
  • Propsを使うことで、コンポーネント間でデータの受け渡しが可能になり、動的な表示が実現できます。
  • Propsを活用して再利用可能なコンポーネントを作成することで、アプリケーションの構造をシンプルに保ちながら、効率的な開発が行えます。

2.2 State(状態)の管理

  • *State(状態)**は、Reactコンポーネントの内部で管理されるデータです。Stateを使用することで、コンポーネントの動的な状態を管理し、ユーザーの操作に応じてUIを更新できます。このセクションでは、Stateの役割と使い方、状態管理の重要性について具体的なコード例を交えて説明します。

1. Stateの役割と使い方

Stateは、コンポーネントの中で変化するデータを保持するために使われます。Reactでは、Stateはコンポーネントの状態を表し、これを使ってUIを制御します。

Stateの定義

Stateは、useStateフックを使って定義します。

javascript
コードをコピーする
import React, { useState } from 'react';

function Counter() {
  // useStateを使ってcountという状態を定義
  const [count, setCount] = useState(0);

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

説明:

  • useStateフックを使ってcountという状態を初期値0で定義しています。
  • ボタンをクリックすると、setCount関数を呼び出してcountを1増やします。

2. 状態管理とコンポーネントの再レンダリング

Stateが変更されると、Reactはそのコンポーネントを再レンダリングします。これにより、UIが自動的に更新され、ユーザーに最新の状態が表示されます。

javascript
コードをコピーする
import React, { useState } from 'react';

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

  const handleIncrement = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={handleIncrement}>カウントアップ</button>
    </div>
  );
}

説明:

  • handleIncrement関数を作成し、ボタンのonClickイベントでこの関数を呼び出しています。
  • setCountを呼び出すと、countが変更され、コンポーネントが再レンダリングされます。

3. 状態を使って簡単なインタラクティブなアプリを作成

ここでは、状態を使った簡単なインタラクティブアプリ、すなわち「カウンター」アプリを作成します。このアプリでは、カウントを増やすだけでなく、リセットする機能も追加します。

javascript
コードをコピーする
import React, { useState } from 'react';

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

  const handleIncrement = () => {
    setCount(count + 1);
  };

  const handleReset = () => {
    setCount(0);
  };

  return (
    <div>
      <h1>カウンターアプリ</h1>
      <p>カウント: {count}</p>
      <button onClick={handleIncrement}>カウントアップ</button>
      <button onClick={handleReset}>リセット</button>
    </div>
  );
}

export default CounterApp;

説明:

  • CounterAppコンポーネント内で、カウントを表示するためのcount状態を定義しています。
  • handleIncrement関数は、カウントを1増やすために使用され、handleReset関数はカウントを0にリセットします。
  • それぞれのボタンに対して、クリックイベントを設定しています。

まとめ

  • Stateは、コンポーネント内部で管理されるデータであり、ユーザーの操作に応じて変化します。
  • Stateが変更されると、Reactは自動的にコンポーネントを再レンダリングし、最新の状態をUIに反映させます。
  • 状態を使って簡単なインタラクティブアプリを作成することで、Reactの強力な状態管理機能を理解することができます。これにより、より動的でユーザーインターフェースが作成できるようになります。

2.3 イベント処理

Reactでは、ユーザーの操作に応じてアプリケーションを反応させるためにイベント処理が重要です。イベント処理を使うことで、ユーザーのアクションに対して何かを実行することができます。このセクションでは、ユーザーイベントの処理方法、イベントハンドラーの作成、そしてイベントを活用したアプリの作成について説明します。


1. ユーザーイベント(クリック、入力、フォーム送信)の処理

ユーザーの操作には、クリック、入力、フォーム送信などがあります。これらの操作を検知して処理するために、Reactではイベントリスナーを設定します。

クリックイベントの例

javascript
コードをコピーする
import React from 'react';

function ClickCounter() {
  const handleClick = () => {
    alert('ボタンがクリックされました!');
  };

  return (
    <div>
      <button onClick={handleClick}>クリックしてください</button>
    </div>
  );
}

説明:

  • handleClick関数は、ボタンがクリックされたときに呼び出されます。
  • onClickプロパティを使用して、ボタンにクリックイベントを設定しています。

2. イベントハンドラーの作成

イベントハンドラーは、特定のユーザーアクションが発生したときに実行される関数です。イベントハンドラーを作成し、それをコンポーネントに組み込むことができます。

入力イベントの例

javascript
コードをコピーする
import React, { useState } from 'react';

function TextInput() {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  return (
    <div>
      <input type="text" value={inputValue} onChange={handleChange} />
      <p>入力されたテキスト: {inputValue}</p>
    </div>
  );
}

説明:

  • handleChange関数は、入力ボックスの内容が変更されたときに呼び出されます。
  • onChangeプロパティを使用して、入力イベントを設定しています。
  • event.target.valueを使って、現在の入力値を取得し、setInputValueで状態を更新しています。

3. イベントを活用したアプリの作成

ここでは、ユーザーからテキストを受け取り、そのテキストを表示する簡単なアプリを作成します。このアプリでは、ユーザーが入力した内容をリアルタイムで表示します。

javascript
コードをコピーする
import React, { useState } from 'react';

function TextDisplayApp() {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault(); // フォームのデフォルトの送信を防止
    alert(`送信されたテキスト: ${inputValue}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={inputValue} onChange={handleChange} placeholder="テキストを入力" />
      <button type="submit">送信</button>
      <p>入力されたテキスト: {inputValue}</p>
    </form>
  );
}

export default TextDisplayApp;

説明:

  • TextDisplayAppコンポーネント内で、入力されたテキストを保持するためのinputValue状態を定義しています。
  • handleChange関数で入力内容を更新し、handleSubmit関数でフォームが送信されたときの処理を行います。event.preventDefault()を使用して、デフォルトのフォーム送信動作を防ぎます。
  • フォーム内のボタンをクリックすると、現在の入力値をアラートとして表示します。また、入力されたテキストを画面にも表示しています。

まとめ

  • Reactでは、ユーザーイベント(クリック、入力、フォーム送信)を処理するためにイベントハンドラーを使用します。
  • イベントハンドラーを作成し、それをコンポーネントに組み込むことで、ユーザーのアクションに応じた動的なUIを実現できます。
  • 状態を使った簡単なインタラクティブアプリを作成することで、ユーザーからの入力を受け取り、それを表示する機能を学びました。これにより、Reactのイベント処理の基本を理解することができます。

3. Reactの実践

3.1 リストとキー

Reactでは、リストをレンダリングすることが非常に一般的です。特に、動的に変化するデータを扱う際に、リストを使うことが多いです。このセクションでは、リストをレンダリングする方法と、リストをレンダリングする際にキーが重要である理由について具体的なコード例を交えて説明します。


1. リストをレンダリングする方法

Reactでは、配列を使ってリストを作成し、map関数を使ってそれをレンダリングすることができます。以下に、簡単なリストの例を示します。

javascript
コードをコピーする
import React from 'react';

function ItemList() {
  const items = ['りんご', 'ばなな', 'みかん'];

  return (
    <ul>
      {items.map((item) => (
        <li key={item}>{item}</li>
      ))}
    </ul>
  );
}

export default ItemList;

説明:

  • itemsという配列にフルーツの名前を格納しています。
  • map関数を使って、各フルーツを<li>要素としてレンダリングしています。
  • 各リストアイテムにはkeyプロパティを設定していますが、これについては次のセクションで詳しく説明します。

2. リストをレンダリングする際のキーの重要性

Reactでは、リストの各要素にユニークなキーを持たせることが重要です。これは、Reactがリストを効率的に再レンダリングできるようにするためです。キーは、各要素の識別子として機能し、リスト内の要素が変更されたり追加されたり削除されたりした際に、Reactがどの要素を再利用するかを判断するのに役立ちます。

キーの例

以下の例では、リストに対してアイテムを追加したり削除したりすることができます。これにより、キーの重要性がよくわかります。

javascript
コードをコピーする
import React, { useState } from 'react';

function TodoList() {
  const [items, setItems] = useState([]);
  const [inputValue, setInputValue] = useState('');

  const handleAddItem = () => {
    if (inputValue) {
      setItems([...items, inputValue]);
      setInputValue(''); // 入力欄をクリア
    }
  };

  const handleRemoveItem = (index) => {
    setItems(items.filter((_, i) => i !== index));
  };

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        placeholder="タスクを追加"
      />
      <button onClick={handleAddItem}>追加</button>
      <ul>
        {items.map((item, index) => (
          <li key={index}>
            {item} <button onClick={() => handleRemoveItem(index)}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoList;

説明:

  • TodoListコンポーネントでは、ユーザーがタスクを追加してリストに表示することができます。
  • handleAddItem関数で新しいタスクを追加し、handleRemoveItem関数でタスクを削除します。
  • リスト内の各要素には、インデックスをキーとして使用していますが、これは一般的には推奨されません。要素の順序が変更される可能性がある場合は、ユニークな識別子を使う方が良いです。

まとめ

  • Reactでは、配列を使ってリストを作成し、map関数でそれをレンダリングできます。
  • リスト内の各要素には、ユニークなキーを設定することが重要です。キーは、要素の識別子として機能し、Reactが効率的に要素を再利用・再レンダリングするのに役立ちます。
  • リストを扱う際には、キーの使い方に注意し、適切な識別子を設定することが大切です。

3.2 条件付きレンダリング

Reactでは、条件に基づいてコンポーネントを表示したり非表示にしたりすることができます。これを条件付きレンダリングと言います。このセクションでは、if文や三項演算子を使った条件付きレンダリングの方法を具体的なコード例を交えて説明します。


1. 条件に基づいてコンポーネントを表示/非表示にする

条件付きレンダリングを使用すると、特定の条件に基づいてUIを動的に変えることができます。例えば、ログイン状態に応じて異なるメッセージを表示する場合などです。

例: ログイン状態に応じたメッセージの表示

javascript
コードをコピーする
import React, { useState } from 'react';

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

  const toggleLogin = () => {
    setIsLoggedIn(!isLoggedIn);
  };

  return (
    <div>
      <button onClick={toggleLogin}>
        {isLoggedIn ? 'ログアウト' : 'ログイン'}
      </button>
      {isLoggedIn ? (
        <p>ようこそ、ユーザーさん!</p>
      ) : (
        <p>ログインしてください。</p>
      )}
    </div>
  );
}

export default LoginMessage;

説明:

  • isLoggedInという状態を持ち、ボタンをクリックすることでログイン状態をトグル(切り替え)します。
  • ボタンのラベルは、ログイン状態に応じて変わります。
  • 三項演算子を使って、isLoggedIntrueのときは「ようこそ、ユーザーさん!」を表示し、falseのときは「ログインしてください。」を表示します。

2. if文や三項演算子を使ったレンダリング

条件付きレンダリングには、if文や三項演算子を使う方法があります。

例: if文を使った条件付きレンダリング

javascript
コードをコピーする
import React, { useState } from 'react';

function Weather() {
  const [weather, setWeather] = useState('晴れ');

  const renderWeatherMessage = () => {
    if (weather === '晴れ') {
      return <p>今日は晴れています!お出かけ日和です。</p>;
    } else if (weather === '') {
      return <p>今日は雨が降っています。傘を持って行きましょう。</p>;
    } else {
      return <p>天気情報がありません。</p>;
    }
  };

  return (
    <div>
      <h1>天気予報</h1>
      {renderWeatherMessage()}
      <button onClick={() => setWeather('')}>雨にする</button>
      <button onClick={() => setWeather('晴れ')}>晴れにする</button>
    </div>
  );
}

export default Weather;

説明:

  • weatherという状態を持ち、天気の状態を管理しています。
  • renderWeatherMessage関数でif文を使って天気に応じたメッセージを返します。
  • ボタンをクリックすると、setWeatherを使って状態が変更され、その結果、表示されるメッセージも変わります。

まとめ

  • 条件付きレンダリングを使うことで、特定の条件に基づいてコンポーネントを表示したり非表示にしたりできます。
  • 三項演算子を使った条件付きレンダリングは簡潔で、短い条件に便利です。
  • if文を使った条件付きレンダリングは、より複雑なロジックを処理するのに適しています。
  • これらの手法を駆使して、動的でインタラクティブなUIを作成することができます。

3.3 フォームの作成と制御

Reactでは、フォームを作成してユーザーからの入力を受け取ることができます。フォーム要素の制御と非制御の違い、そしてフォームデータの処理と状態管理について、具体的なコード例を交えて説明します。


1. フォーム要素の制御と非制御

Reactのフォームは、主に制御コンポーネント非制御コンポーネントの2つの方法で管理できます。

  • 制御コンポーネント: フォーム要素の値をReactの状態で管理する方法です。これにより、状態がUIに直接反映されます。
  • 非制御コンポーネント: フォーム要素の値を直接DOMから取得する方法です。Reactの状態とは独立して動作します。

制御コンポーネントの例

javascript
コードをコピーする
import React, { useState } from 'react';

function ControlledForm() {
  const [name, setName] = useState('');

  const handleChange = (event) => {
    setName(event.target.value); // 入力された値を状態に設定
  };

  const handleSubmit = (event) => {
    event.preventDefault(); // フォームのデフォルト送信を防ぐ
    alert(`こんにちは、${name}さん!`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        名前:
        <input type="text" value={name} onChange={handleChange} />
      </label>
      <button type="submit">送信</button>
    </form>
  );
}

export default ControlledForm;

説明:

  • nameという状態を管理し、setNameでその値を更新します。
  • onChangeイベントで入力内容を取得し、状態に反映します。
  • フォームが送信されると、アラートで入力された名前を表示します。

非制御コンポーネントの例

javascript
コードをコピーする
import React, { useRef } from 'react';

function UncontrolledForm() {
  const nameRef = useRef(); // useRefを使って参照を取得

  const handleSubmit = (event) => {
    event.preventDefault(); // フォームのデフォルト送信を防ぐ
    alert(`こんにちは、${nameRef.current.value}さん!`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        名前:
        <input type="text" ref={nameRef} /> {/* refを使ってDOM要素にアクセス */}
      </label>
      <button type="submit">送信</button>
    </form>
  );
}

export default UncontrolledForm;

説明:

  • useRefを使って、nameRefという参照を作成します。
  • 入力フィールドのref属性にnameRefを設定し、直接DOM要素にアクセスします。
  • フォームが送信されると、nameRef.current.valueを使って入力された名前を取得します。

2. フォームデータの処理と状態管理

フォームからのデータを処理するために、状態管理を使って入力内容を取得し、必要なアクションを実行します。これにより、アプリケーションがユーザーの入力に基づいて動的に反応します。

複数の入力を持つ制御コンポーネントの例

javascript
コードをコピーする
import React, { useState } from 'react';

function MultiFieldForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
  });

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData((prevData) => ({
      ...prevData,
      [name]: value, // フィールド名に基づいて状態を更新
    }));
  };

  const handleSubmit = (event) => {
    event.preventDefault(); // フォームのデフォルト送信を防ぐ
    alert(`名前: ${formData.name}\nメール: ${formData.email}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        名前:
        <input type="text" name="name" value={formData.name} onChange={handleChange} />
      </label>
      <label>
        メール:
        <input type="email" name="email" value={formData.email} onChange={handleChange} />
      </label>
      <button type="submit">送信</button>
    </form>
  );
}

export default MultiFieldForm;

説明:

  • formDataという状態を持ち、名前とメールの2つのフィールドを管理します。
  • handleChange関数では、name属性に基づいて状態を更新します。これにより、複数の入力フィールドを効率的に管理できます。
  • フォームが送信されると、アラートで両方の入力値を表示します。

まとめ

  • 制御コンポーネントは、フォーム要素の値をReactの状態で管理し、ユーザーの入力をリアルタイムで反映します。
  • 非制御コンポーネントは、DOMから直接値を取得し、Reactの状態とは独立して動作します。
  • フォームデータの処理と状態管理を理解することで、ユーザーからの入力に基づいてアプリケーションを動的に反応させることができます。
  • 複数の入力フィールドを管理する方法を学ぶことで、より複雑なフォームを作成することができるようになります。

3.4 APIとの連携(データフェッチング)

Reactアプリケーションでは、外部APIからデータを取得して表示することが一般的です。このセクションでは、fetchaxiosを使ってデータを取得する方法、非同期処理の基本(Promise、async/await)、および取得したデータを表示する方法について説明します。


1. fetchを使ってデータを取得

fetchは、Web APIに対してHTTPリクエストを送信するための組み込みのJavaScript関数です。

例: fetchを使ったデータ取得

javascript
コードをコピーする
import React, { useState, useEffect } from 'react';

function FetchDataExample() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts');
        if (!response.ok) {
          throw new Error('ネットワークエラーが発生しました');
        }
        const jsonData = await response.json();
        setData(jsonData);
      } catch (error) {
        setError(error.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []); // コンポーネントが初回マウントされた時に実行

  if (loading) {
    return <p>読み込み中...</p>;
  }

  if (error) {
    return <p>エラー: {error}</p>;
  }

  return (
    <div>
      <h1>取得したデータ</h1>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
}

export default FetchDataExample;

説明:

  • useEffectフックを使って、コンポーネントがマウントされたときにデータを取得します。
  • fetch関数を使ってAPIにリクエストを送り、レスポンスを取得します。
  • データ取得中はloading状態をtrueに設定し、エラーが発生した場合はerror状態を更新します。
  • データが取得できたら、setDataで状態を更新し、リストとして表示します。

2. axiosを使ったデータ取得

axiosは、PromiseベースのHTTPクライアントで、使いやすさと機能の豊富さから多くの開発者に人気があります。axiosを使うには、まずインストールが必要です。

bash
コードをコピーする
npm install axios

例: axiosを使ったデータ取得

javascript
コードをコピーする
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function AxiosExample() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
        setData(response.data); // 取得したデータを状態に設定
      } catch (error) {
        setError(error.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  if (loading) {
    return <p>読み込み中...</p>;
  }

  if (error) {
    return <p>エラー: {error}</p>;
  }

  return (
    <div>
      <h1>取得したデータ</h1>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
}

export default AxiosExample;

説明:

  • axiosをインポートして使用します。
  • axios.getを使ってAPIからデータを取得し、setDataで状態を更新します。
  • エラーハンドリングも同様に行いますが、axiosの場合はレスポンスエラーも捕捉できます。

3. 非同期処理(Promise、async/await)の基本

非同期処理は、データを取得する際によく使われる方法です。Promiseやasync/awaitを使用することで、コードをより読みやすくすることができます。

  • Promise: 非同期操作の結果を表すオブジェクトです。成功時と失敗時の処理を指定できます。
  • async/await: Promiseを使った非同期処理をより簡潔に書くための構文です。async関数内でawaitを使うことで、Promiseが解決されるのを待つことができます。

まとめ

  • fetchaxiosを使って外部APIからデータを取得し、Reactコンポーネントで表示することができます。
  • useEffectフックを利用して、コンポーネントがマウントされた際にデータを取得するのが一般的です。
  • 非同期処理の基本(Promise、async/await)を理解することで、データの取得とエラーハンドリングを効率的に行えます。
  • 取得したデータは、コンポーネントの状態に設定し、UIに反映させることができます。

4. 高度なトピック

4.1 useEffectフック

useEffectフックは、Reactコンポーネントにおいて副作用を管理するための重要なフックです。副作用とは、データのフェッチング、DOMの操作、サブスクリプションの設定など、コンポーネントのレンダリングに影響を与えないが、他の処理や状態に依存する処理のことを指します。このセクションでは、useEffectの基礎、ライフサイクル、データのフェッチングやDOM操作について具体的なコード例を用いて説明します。


1. useEffectの基礎

useEffectフックは、コンポーネントがレンダリングされた後に実行される副作用を定義します。基本的な使い方は以下の通りです。

例: useEffectの基本的な使用法

javascript
コードをコピーする
import React, { useState, useEffect } from 'react';

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

  // useEffectを使って副作用を管理
  useEffect(() => {
    console.log(`カウントが${count}になりました!`);

    // クリーンアップ関数
    return () => {
      console.log(`カウントが${count}から変わる前にクリーンアップ`);
    };
  }, [count]); // countが変更されるたびに実行

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

export default Counter;

説明:

  • useEffectは、countが変更されるたびに実行されます。
  • 副作用の内容は、カウントの値をコンソールにログとして出力することです。
  • クリーンアップ関数を返すことで、コンポーネントがアンマウントされるときや次の実行前に実行されます。これにより、メモリリークを防ぐことができます。

2. 副作用の管理とライフサイクル

useEffectは、コンポーネントのライフサイクルに関連して実行されます。具体的には、以下の3つの状況で実行されます。

  • コンポーネントがマウントされたとき
  • 依存配列の値が変更されたとき
  • コンポーネントがアンマウントされるとき

依存配列を空にすると、コンポーネントがマウントされたときだけに実行されます。

例: マウント時のみ実行

javascript
コードをコピーする
import React, { useEffect } from 'react';

function Hello() {
  useEffect(() => {
    console.log('コンポーネントがマウントされました!');

    // クリーンアップ関数
    return () => {
      console.log('コンポーネントがアンマウントされました!');
    };
  }, []); // 空の依存配列

  return <h1>こんにちは!</h1>;
}

export default Hello;

説明:

  • このコンポーネントは、マウント時に「コンポーネントがマウントされました!」と表示し、アンマウント時に「コンポーネントがアンマウントされました!」と表示します。

3. データのフェッチングやDOM操作

useEffectは、データのフェッチングやDOM操作にも利用されます。例えば、APIからデータを取得して状態を更新することができます。

例: データのフェッチング

javascript
コードをコピーする
import React, { useState, useEffect } from 'react';

function DataFetching() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts');
        if (!response.ok) {
          throw new Error('ネットワークエラーが発生しました');
        }
        const jsonData = await response.json();
        setData(jsonData);
      } catch (error) {
        setError(error.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []); // コンポーネントがマウントされたときに実行

  if (loading) return <p>読み込み中...</p>;
  if (error) return <p>エラー: {error}</p>;

  return (
    <div>
      <h1>取得したデータ</h1>
      <ul>
        {data.map(item => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
}

export default DataFetching;

説明:

  • fetchData関数をuseEffect内で定義し、コンポーネントがマウントされたときに実行します。
  • APIからデータを取得し、取得したデータを状態に設定します。
  • データが読み込まれているときやエラーが発生したときの状態を適切に表示します。

まとめ

  • useEffectフックは、副作用を管理するための重要なツールで、ライフサイクルに関連した処理を行うことができます。
  • マウント、変更、アンマウントの各ステージで実行されるため、データのフェッチングやDOMの操作に非常に便利です。
  • 依存配列を使用することで、特定の状態やプロパティが変更されたときにのみ実行することができます。
  • これにより、効率的かつ安全にReactコンポーネントを構築することが可能です。

4.2 useStateフックの応用

useStateフックを使って状態を管理する際、単純な値だけでなく、オブジェクトや配列のような複雑な状態も扱うことができます。このセクションでは、複雑な状態の管理方法、オブジェクトや配列の状態更新について具体的なコード例を交えて説明します。


1. 複雑な状態の管理

複雑な状態とは、オブジェクトや配列の形を持つ状態のことです。これを使うことで、関連するデータを一つの状態として管理できます。

例: 複雑な状態を管理するコンポーネント

javascript
コードをコピーする
import React, { useState } from 'react';

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

  const handleChange = (event) => {
    const { name, value } = event.target;
    setUser((prevUser) => ({
      ...prevUser, // 以前の状態をコピー
      [name]: value, // 変更されたフィールドのみ更新
    }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    alert(`ユーザー情報:\n名前: ${user.name}\nメール: ${user.email}\n年齢: ${user.age}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        名前:
        <input type="text" name="name" value={user.name} onChange={handleChange} />
      </label>
      <label>
        メール:
        <input type="email" name="email" value={user.email} onChange={handleChange} />
      </label>
      <label>
        年齢:
        <input type="number" name="age" value={user.age || ''} onChange={handleChange} />
      </label>
      <button type="submit">送信</button>
    </form>
  );
}

export default UserProfile;

説明:

  • userというオブジェクトを状態として持ち、名前、メール、年齢の3つのフィールドを管理します。
  • handleChange関数では、変更されたフィールドの名前を使って、オブジェクトの特定のキーのみを更新します。
  • フォームが送信されると、現在のユーザー情報をアラートで表示します。

2. オブジェクトや配列の状態更新

オブジェクトの状態更新

上記の例のように、オブジェクトの状態を更新する際は、スプレッド構文(...)を使用して、以前の状態を保持しつつ必要なフィールドのみを更新します。

配列の状態更新

配列の場合、特定の要素を追加・削除・更新することができます。以下に、配列を使った状態管理の例を示します。

例: 配列を管理するコンポーネント

javascript
コードをコピーする
import React, { useState } from 'react';

function TodoList() {
  const [todos, setTodos] = useState([]); // 初期状態は空の配列
  const [inputValue, setInputValue] = useState('');

  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  const addTodo = (event) => {
    event.preventDefault();
    if (inputValue.trim() === '') return; // 空の入力は無視

    setTodos((prevTodos) => [...prevTodos, inputValue]); // 新しいタスクを追加
    setInputValue(''); // 入力フィールドをクリア
  };

  const removeTodo = (index) => {
    setTodos((prevTodos) => prevTodos.filter((_, i) => i !== index)); // 特定のタスクを削除
  };

  return (
    <div>
      <h1>Todoリスト</h1>
      <form onSubmit={addTodo}>
        <input type="text" value={inputValue} onChange={handleChange} />
        <button type="submit">追加</button>
      </form>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>
            {todo} <button onClick={() => removeTodo(index)}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoList;

説明:

  • todosという配列を状態として持ち、Todoタスクを管理します。
  • addTodo関数では、setTodosを使って新しいタスクを配列に追加します。...prevTodosを使って以前のタスクを保持し、新しいタスクをその後に追加しています。
  • removeTodo関数では、特定のインデックスにあるタスクを削除するために、filterメソッドを使用します。
  • フォームに入力したタスクをリストとして表示し、削除ボタンで特定のタスクを削除できます。

まとめ

  • useStateフックを使用して、複雑な状態(オブジェクトや配列)を管理することができます。
  • スプレッド構文を使って状態を簡単に更新することができ、特定のフィールドや要素のみを変更できます。
  • 状態の変更はReactの再レンダリングを引き起こすため、UIが常に最新の情報を反映します。
  • このように、複雑な状態を効率的に管理することで、より動的でインタラクティブなアプリケーションを作成できます。

4.3 React Routerによるルーティング

React Routerは、シングルページアプリケーション(SPA)におけるルーティングを管理するためのライブラリです。これにより、アプリケーション内で異なるページ間を遷移することができ、ユーザーにスムーズな体験を提供します。このセクションでは、React Routerの基本的な使い方と、ページ間の移動、パラメータの扱いについて具体的なコード例を交えて説明します。


1. シングルページアプリケーション(SPA)のルーティング

SPAでは、ブラウザがページ全体をリロードすることなく、異なるビューを表示するために、JavaScriptを使ってコンテンツを動的に更新します。React Routerを使用することで、URLに基づいて表示するコンポーネントを制御できます。


2. React Routerのセットアップと使い方

まず、React Routerをインストールします。プロジェクトのディレクトリで以下のコマンドを実行してください。

bash
コードをコピーする
npm install react-router-dom

次に、React Routerを使って基本的なルーティングを設定します。

例: 基本的なルーティングの設定

javascript
コードをコピーする
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';

function Home() {
  return <h2>ホームページ</h2>;
}

function About() {
  return <h2>アバウトページ</h2>;
}

function NotFound() {
  return <h2>404 - ページが見つかりません</h2>;
}

function App() {
  return (
    <Router>
      <nav>
        <ul>
          <li>
            <Link to="/">ホーム</Link>
          </li>
          <li>
            <Link to="/about">アバウト</Link>
          </li>
        </ul>
      </nav>
      <Switch>
        <Route path="/" exact component={Home} />
        <Route path="/about" component={About} />
        <Route component={NotFound} />
      </Switch>
    </Router>
  );
}

export default App;

説明:

  • BrowserRouterを使用してアプリケーションをラップします。
  • Linkコンポーネントを使用して、異なるページへのリンクを作成します。
  • Switchコンポーネントは、最初に一致するRouteのみを表示します。
  • Routeは、特定のURLパスにマッチした場合に指定したコンポーネントを表示します。

3. ページ間の移動とパラメータの扱い

ページ間の移動は、Linkコンポーネントを使用して簡単に行えます。また、URLパラメータを使用して動的にコンテンツを表示することも可能です。

例: URLパラメータの使用

javascript
コードをコピーする
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link, useParams } from 'react-router-dom';

function Home() {
  return <h2>ホームページ</h2>;
}

function User() {
  const { userId } = useParams(); // URLパラメータを取得
  return <h2>ユーザーID: {userId}</h2>;
}

function App() {
  return (
    <Router>
      <nav>
        <ul>
          <li>
            <Link to="/">ホーム</Link>
          </li>
          <li>
            <Link to="/user/1">ユーザー 1</Link>
          </li>
          <li>
            <Link to="/user/2">ユーザー 2</Link>
          </li>
        </ul>
      </nav>
      <Switch>
        <Route path="/" exact component={Home} />
        <Route path="/user/:userId" component={User} /> {/* :userIdがURLパラメータ */}
      </Switch>
    </Router>
  );
}

export default App;

説明:

  • Userコンポーネントでは、useParamsフックを使ってURLパラメータ(userId)を取得します。
  • /user/1/user/2にアクセスすると、それぞれのユーザーIDが表示されます。

まとめ

  • React Routerは、シングルページアプリケーションにおけるルーティングを簡単に管理するためのライブラリです。
  • BrowserRouterRouteSwitchLinkを使用して、ページ間の遷移を実現します。
  • URLパラメータを使用することで、動的にコンテンツを表示することができ、アプリケーションの柔軟性を向上させます。
  • React Routerを使用することで、ユーザーにシームレスな体験を提供することが可能になります。

4.4 コンテキストAPI

ReactのコンテキストAPIは、アプリケーション内でグローバルな状態を管理し、プロパティ(props)を直接渡さずにデータを共有できる仕組みです。このセクションでは、グローバルな状態管理の必要性、React Context APIの使い方、そしてPropsドリリングを解消する方法について具体的なコード例を交えて説明します。


1. グローバルな状態管理の必要性

アプリケーションが大きくなると、異なるコンポーネント間でデータを共有する必要が増えます。この時、親から子へ、またその子から孫へとデータを渡すこと(Propsドリリング)が発生します。これはコードが煩雑になり、メンテナンスが難しくなります。

例: Propsドリリングの問題

javascript
コードをコピーする
function Grandchild({ name }) {
  return <h2>{name}</h2>;
}

function Child({ name }) {
  return <Grandchild name={name} />;
}

function Parent() {
  const name = "John Doe";
  return <Child name={name} />;
}

この例では、nameParentからGrandchildに渡すためにChildを通す必要があります。このような場合に、コンテキストAPIを使うと、直接Grandchildnameを渡すことができます。


2. React Context APIの使い方

React Context APIは、createContextuseContextを使用して作成・利用します。まず、コンテキストを作成し、Providerを使ってその値を提供します。

例: コンテキストの作成と利用

javascript
コードをコピーする
import React, { createContext, useContext } from 'react';

// コンテキストを作成
const NameContext = createContext();

function Grandchild() {
  // useContextを使ってコンテキストの値を取得
  const name = useContext(NameContext);
  return <h2>{name}</h2>;
}

function Child() {
  return <Grandchild />;
}

function Parent() {
  const name = "John Doe";

  return (
    // Providerを使ってコンテキストの値を提供
    <NameContext.Provider value={name}>
      <Child />
    </NameContext.Provider>
  );
}

export default Parent;

説明:

  • createContext()で新しいコンテキストを作成します。
  • NameContext.Providerを使って、nameの値を提供します。
  • GrandchildコンポーネントでuseContext(NameContext)を使って、コンテキストの値を直接取得します。

3. Propsドリリングを解消する方法

コンテキストAPIを使用することで、Propsドリリングの問題を解消し、必要なデータを直接取得できます。これにより、コードの可読性が向上し、メンテナンスが楽になります。

例: 複数のコンポーネントでコンテキストを利用する

javascript
コードをコピーする
import React, { createContext, useContext } from 'react';

// コンテキストを作成
const ThemeContext = createContext();

function Button() {
  const theme = useContext(ThemeContext);
  return <button style={{ backgroundColor: theme.background, color: theme.color }}>テーマボタン</button>;
}

function Toolbar() {
  return <Button />;
}

function App() {
  const theme = {
    background: 'blue',
    color: 'white'
  };

  return (
    <ThemeContext.Provider value={theme}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

export default App;

説明:

  • ThemeContextを作成し、themeオブジェクトを提供します。
  • ButtonコンポーネントでuseContext(ThemeContext)を使って、テーマのスタイルを取得し、ボタンのスタイルを設定します。
  • ToolbarコンポーネントはButtonを子として持ちますが、themeを直接渡す必要はありません。

まとめ

  • コンテキストAPIは、グローバルな状態管理を簡単に実現するための強力なツールです。
  • Propsドリリングの問題を解消し、コンポーネント間でデータを効率的に共有できます。
  • createContextuseContextを使うことで、データの提供と取得が簡単になります。
  • アプリケーションが大規模になるにつれて、コンテキストAPIを使用することで、コードの可読性とメンテナンス性が向上します。

5. プロジェクト演習

5.1 ToDoリストアプリの作成

このセクションでは、基本的なToDoリストアプリを作成します。このアプリでは、ユーザーがタスクを追加したり、表示したり、削除したりできるようにします。フォームの入力や状態管理、イベント処理を通じて、Reactの基本を総合的に学びます。


1. フォームの入力と状態管理

まずは、タスクを追加するためのフォームを作成します。タスクは状態として管理し、ユーザーが入力した内容を取得します。

例: ToDoリストアプリの基本構成

javascript
コードをコピーする
import React, { useState } from 'react';

function ToDoApp() {
  const [task, setTask] = useState(''); // タスクの状態
  const [tasks, setTasks] = useState([]); // タスクのリスト

  // タスクの追加
  const addTask = (e) => {
    e.preventDefault(); // フォームのデフォルト動作を防ぐ
    if (task) {
      setTasks([...tasks, task]); // 新しいタスクをリストに追加
      setTask(''); // 入力フィールドをリセット
    }
  };

  return (
    <div>
      <h1>ToDoリスト</h1>
      <form onSubmit={addTask}>
        <input
          type="text"
          value={task}
          onChange={(e) => setTask(e.target.value)} // 入力値を状態にセット
          placeholder="タスクを入力"
        />
        <button type="submit">追加</button>
      </form>
      <ul>
        {tasks.map((t, index) => (
          <li key={index}>{t}</li> // タスクをリスト表示
        ))}
      </ul>
    </div>
  );
}

export default ToDoApp;

説明:

  • useStateフックを使って、タスクの入力内容とタスクリストの状態を管理します。
  • フォームのonSubmitイベントでaddTask関数を呼び出し、タスクをリストに追加します。
  • 入力フィールドは、valueプロパティで状態と連動しており、onChangeイベントで状態を更新します。

2. リストの表示、追加、削除

次に、タスクを表示するだけでなく、タスクを削除できる機能を追加します。

例: タスクの削除機能を追加

javascript
コードをコピーする
import React, { useState } from 'react';

function ToDoApp() {
  const [task, setTask] = useState('');
  const [tasks, setTasks] = useState([]);

  const addTask = (e) => {
    e.preventDefault();
    if (task) {
      setTasks([...tasks, task]);
      setTask('');
    }
  };

  // タスクを削除する関数
  const deleteTask = (index) => {
    const newTasks = tasks.filter((_, i) => i !== index); // 指定したインデックス以外のタスクを取得
    setTasks(newTasks); // 新しいタスクリストに更新
  };

  return (
    <div>
      <h1>ToDoリスト</h1>
      <form onSubmit={addTask}>
        <input
          type="text"
          value={task}
          onChange={(e) => setTask(e.target.value)}
          placeholder="タスクを入力"
        />
        <button type="submit">追加</button>
      </form>
      <ul>
        {tasks.map((t, index) => (
          <li key={index}>
            {t}
            <button onClick={() => deleteTask(index)}>削除</button> {/* 削除ボタン */}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default ToDoApp;

説明:

  • deleteTask関数を追加し、指定したインデックスのタスクを削除します。
  • filterメソッドを使って、削除対象のタスク以外を新しい配列として取得します。
  • タスクリストを表示する際に、各タスクに削除ボタンを追加し、クリック時にdeleteTaskを呼び出します。

3. 状態とイベント処理を総合的に学ぶ

このToDoリストアプリでは、状態管理、イベント処理、フォーム入力、リスト表示といった基本的なReactの機能を総合的に学ぶことができます。これにより、Reactの理解が深まるでしょう。


まとめ

  • ユーザーからの入力を状態として管理し、フォームを使ってデータを追加します。
  • リストを表示し、ユーザーがタスクを削除できる機能を追加しました。
  • 状態とイベント処理の組み合わせを通じて、Reactの基本的な使い方を学びました。

このアプリは、さらに機能を追加して拡張することが可能です。たとえば、タスクの完了状態を管理したり、ローカルストレージにデータを保存したりすることが考えられます。次のステップとして、これらの機能を実装することをお勧めします。

5.2 簡単なメモアプリの作成

このセクションでは、ローカルストレージを使用してメモを保存する簡単なメモアプリを作成します。さらに、カスタムフックを作成し、コンポーネントのリファクタリングを行います。このアプリを通じて、状態管理やデータの永続化の方法を学びます。


1. ローカルストレージを使ったデータの保存

まずは、メモをローカルストレージに保存し、アプリを再起動してもデータが残るようにします。ローカルストレージを利用することで、ブラウザのストレージにデータを保存できます。

例: ローカルストレージを使ったメモアプリ

javascript
コードをコピーする
import React, { useState, useEffect } from 'react';

function MemoApp() {
  const [memo, setMemo] = useState(''); // メモの状態
  const [memos, setMemos] = useState([]); // メモのリスト

  // コンポーネントがマウントされた時にローカルストレージからメモを読み込む
  useEffect(() => {
    const savedMemos = JSON.parse(localStorage.getItem('memos')) || []; // ローカルストレージからメモを取得
    setMemos(savedMemos);
  }, []);

  // メモを追加する関数
  const addMemo = (e) => {
    e.preventDefault();
    if (memo) {
      const newMemos = [...memos, memo];
      setMemos(newMemos);
      setMemo('');
      localStorage.setItem('memos', JSON.stringify(newMemos)); // メモをローカルストレージに保存
    }
  };

  return (
    <div>
      <h1>メモアプリ</h1>
      <form onSubmit={addMemo}>
        <input
          type="text"
          value={memo}
          onChange={(e) => setMemo(e.target.value)}
          placeholder="メモを入力"
        />
        <button type="submit">追加</button>
      </form>
      <ul>
        {memos.map((m, index) => (
          <li key={index}>{m}</li> // メモをリスト表示
        ))}
      </ul>
    </div>
  );
}

export default MemoApp;

説明:

  • useEffectを使用して、コンポーネントがマウントされたときにローカルストレージからメモを取得し、setMemosで状態を更新します。
  • addMemo関数では、新しいメモをリストに追加し、その後ローカルストレージに保存します。

2. カスタムフックの作成

状態管理やローカルストレージへの読み書きを行うためのカスタムフックを作成します。これにより、コードの再利用性が向上します。

例: useLocalStorageフックの作成

javascript
コードをコピーする
import { useState, useEffect } from 'react';

// カスタムフック: useLocalStorage
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue];
}

export default useLocalStorage;

説明:

  • useLocalStorageカスタムフックは、指定したキーに対してローカルストレージに保存する機能を提供します。
  • 初期値を設定し、状態が更新されるたびにローカルストレージも更新されます。

次に、このカスタムフックをメモアプリに組み込みます。

javascript
コードをコピーする
import React from 'react';
import useLocalStorage from './useLocalStorage'; // カスタムフックをインポート

function MemoApp() {
  const [memo, setMemo] = useState('');
  const [memos, setMemos] = useLocalStorage('memos', []); // カスタムフックを使う

  const addMemo = (e) => {
    e.preventDefault();
    if (memo) {
      setMemos([...memos, memo]); // メモを追加
      setMemo('');
    }
  };

  return (
    <div>
      <h1>メモアプリ</h1>
      <form onSubmit={addMemo}>
        <input
          type="text"
          value={memo}
          onChange={(e) => setMemo(e.target.value)}
          placeholder="メモを入力"
        />
        <button type="submit">追加</button>
      </form>
      <ul>
        {memos.map((m, index) => (
          <li key={index}>{m}</li>
        ))}
      </ul>
    </div>
  );
}

export default MemoApp;

説明:

  • useLocalStorageフックを使って、ローカルストレージの読み書きを簡潔に行います。

3. コンポーネントのリファクタリング

メモの表示部分を別のコンポーネントに分割し、リファクタリングを行います。

例: MemoListコンポーネントの作成

javascript
コードをコピーする
import React from 'react';

function MemoList({ memos }) {
  return (
    <ul>
      {memos.map((m, index) => (
        <li key={index}>{m}</li>
      ))}
    </ul>
  );
}

export default MemoList;

次に、MemoAppにこの新しいコンポーネントを統合します。

javascript
コードをコピーする
import React, { useState } from 'react';
import useLocalStorage from './useLocalStorage';
import MemoList from './MemoList'; // MemoListをインポート

function MemoApp() {
  const [memo, setMemo] = useState('');
  const [memos, setMemos] = useLocalStorage('memos', []);

  const addMemo = (e) => {
    e.preventDefault();
    if (memo) {
      setMemos([...memos, memo]);
      setMemo('');
    }
  };

  return (
    <div>
      <h1>メモアプリ</h1>
      <form onSubmit={addMemo}>
        <input
          type="text"
          value={memo}
          onChange={(e) => setMemo(e.target.value)}
          placeholder="メモを入力"
        />
        <button type="submit">追加</button>
      </form>
      <MemoList memos={memos} /> {/* MemoListコンポーネントを使用 */}
    </div>
  );
}

export default MemoApp;

説明:

  • MemoListコンポーネントを作成し、メモの表示を担当させます。これにより、MemoAppがよりシンプルで可読性が高くなります。

まとめ

  • ローカルストレージを使用してメモを永続化し、アプリの再起動時にもデータが保持されることを実現しました。
  • カスタムフックを作成することで、ローカルストレージとのやり取りを簡潔に行えるようにしました。
  • メモの表示部分を分離したことで、コンポーネントの可読性と再利用性を向上させました。

このメモアプリは、さらに機能を追加して拡張することが可能です。たとえば、メモの編集機能や削除機能、タスクの完了状態の管理などが考えられます。次のステップとして、これらの機能を実装することをお勧めします。

6. 最終プロジェクト:ポートフォリオサイトの作成

6. 最終プロジェクト:ポートフォリオサイトの作成

このセクションでは、Reactの基本機能を使って個人のポートフォリオサイトを作成します。このプロジェクトを通じて、自己紹介、プロジェクトリスト、問い合わせフォームを含むページ構成を実現します。また、状態管理やコンポーネントの構成を強化し、Reactの理解を深めます。


1. プロジェクトのセットアップ

まず、Create React Appを使って新しいプロジェクトを作成します。

bash
コードをコピーする
npx create-react-app my-portfolio
cd my-portfolio
npm start


2. プロジェクトのディレクトリ構成

以下のようなディレクトリ構成を作成します。

css
コードをコピーする
my-portfolio/
├── src/
   ├── components/
      ├── Header.js
      ├── About.js
      ├── Projects.js
      ├── Contact.js
      └── Footer.js
   ├── App.js
   └── index.js


3. コンポーネントの作成

次に、各コンポーネントを作成します。

3.1. Header.js

サイトのヘッダー部分を作成します。

javascript
コードをコピーする
// src/components/Header.js
import React from 'react';

function Header() {
  return (
    <header>
      <h1>私のポートフォリオ</h1>
      <nav>
        <ul>
          <li><a href="#about">自己紹介</a></li>
          <li><a href="#projects">プロジェクト</a></li>
          <li><a href="#contact">お問い合わせ</a></li>
        </ul>
      </nav>
    </header>
  );
}

export default Header;

3.2. About.js

自己紹介部分を作成します。

javascript
コードをコピーする
// src/components/About.js
import React from 'react';

function About() {
  return (
    <section id="about">
      <h2>自己紹介</h2>
      <p>私はフロントエンドエンジニアで、Reactを使った開発が得意です。</p>
    </section>
  );
}

export default About;

3.3. Projects.js

プロジェクトリスト部分を作成します。

javascript
コードをコピーする
// src/components/Projects.js
import React from 'react';

const projects = [
  { id: 1, title: 'プロジェクトA', description: 'これはプロジェクトAの説明です。' },
  { id: 2, title: 'プロジェクトB', description: 'これはプロジェクトBの説明です。' },
  { id: 3, title: 'プロジェクトC', description: 'これはプロジェクトCの説明です。' },
];

function Projects() {
  return (
    <section id="projects">
      <h2>プロジェクト</h2>
      <ul>
        {projects.map(project => (
          <li key={project.id}>
            <h3>{project.title}</h3>
            <p>{project.description}</p>
          </li>
        ))}
      </ul>
    </section>
  );
}

export default Projects;

3.4. Contact.js

お問い合わせフォームを作成します。

javascript
コードをコピーする
// src/components/Contact.js
import React, { useState } from 'react';

function Contact() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [message, setMessage] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    alert(`メッセージが送信されました!\n名前: ${name}\nメール: ${email}\nメッセージ: ${message}`);
    // フォームの入力をリセット
    setName('');
    setEmail('');
    setMessage('');
  };

  return (
    <section id="contact">
      <h2>お問い合わせ</h2>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          placeholder="名前"
          value={name}
          onChange={(e) => setName(e.target.value)}
          required
        />
        <input
          type="email"
          placeholder="メール"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
        />
        <textarea
          placeholder="メッセージ"
          value={message}
          onChange={(e) => setMessage(e.target.value)}
          required
        />
        <button type="submit">送信</button>
      </form>
    </section>
  );
}

export default Contact;

3.5. Footer.js

サイトのフッター部分を作成します。

javascript
コードをコピーする
// src/components/Footer.js
import React from 'react';

function Footer() {
  return (
    <footer>
      <p>© 2024 私のポートフォリオ</p>
    </footer>
  );
}

export default Footer;


4. App.jsの更新

作成したコンポーネントをApp.jsに統合します。

javascript
コードをコピーする
// src/App.js
import React from 'react';
import Header from './components/Header';
import About from './components/About';
import Projects from './components/Projects';
import Contact from './components/Contact';
import Footer from './components/Footer';

function App() {
  return (
    <div>
      <Header />
      <main>
        <About />
        <Projects />
        <Contact />
      </main>
      <Footer />
    </div>
  );
}

export default App;


5. スタイルの追加

基本的なスタイルを追加して、サイトを見栄え良くします。src/index.cssを編集します。

css
コードをコピーする
/* src/index.css */
body {
  font-family: Arial, sans-serif;
  line-height: 1.6;
  margin: 0;
  padding: 0;
  background-color: #f4f4f4;
}

header {
  background: #333;
  color: #fff;
  padding: 10px 20px;
  text-align: center;
}

nav ul {
  list-style: none;
  padding: 0;
}

nav ul li {
  display: inline;
  margin: 0 10px;
}

nav ul li a {
  color: #fff;
  text-decoration: none;
}

section {
  padding: 20px;
  margin: 20px 0;
  background: #fff;
}

footer {
  text-align: center;
  padding: 10px 0;
  background: #333;
  color: #fff;
}


6. 最終チェック

全てのコードを統合したら、npm startを実行してアプリを起動し、ブラウザで動作を確認します。

まとめ

このポートフォリオサイトのプロジェクトを通じて、以下のことを学びました。

  • Reactコンポーネントの作成と組み合わせ
  • 状態管理の基礎とフォームの処理
  • コンポーネントを分割してコードを整理する方法

これを基に、自分のプロジェクトや作品を追加し、さらなる機能拡張を行うことで、より良いポートフォリオサイトを作成してください!

4
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?