Reactでユーザー一覧アプリを作ろう

― 状態・イベント・API連携の実践


はじめに

前回の記事では、Reactの基本概念である「コンポーネント」「JSX」「useState」について学びました。今回は、それらの知識を活用し、外部APIからデータを取得して表示するユーザー一覧アプリをReactで構築していきます。

JavaScriptだけで作ったミニアプリでは、DOMを手動で操作していましたが、Reactでは状態(state)に応じて自動的にUIが再レンダリングされるため、よりシンプルかつ拡張しやすいコードが書けるようになります。

この記事では次のことを実装します:

  • useStateでデータを状態として保持
  • useEffectでAPI通信を行う
  • .map()でデータをループ表示
  • 状態に応じた検索機能の実装

アプリの仕様とゴール

今回作るReactアプリの仕様は以下のとおりです:

  • ページ読み込み時にランダムユーザーAPIからデータを取得
  • ユーザーの名前・画像・メールを一覧で表示
  • 検索ボックスで名前による絞り込みが可能

完成イメージとしては、これまでVanilla JSで作ってきたユーザー検索アプリを、React流で組み直す形です。


セットアップ(ViteでReact環境を用意)

以下のコマンドでプロジェクトを作成しましょう:

npm create vite@latest react-user-app -- --template react
cd react-user-app
npm install
npm run dev

これで開発サーバーが起動し、Reactアプリの雛形が動作します。


Appコンポーネントの実装

以下のコードは、src/App.jsx に記述します。

import { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [users, setUsers] = useState([]);
  const [search, setSearch] = useState('');

  useEffect(() => {
    fetch('https://randomuser.me/api/?results=20')
      .then(res => res.json())
      .then(data => {
        setUsers(data.results);
      })
      .catch(err => {
        console.error('ユーザー取得エラー:', err);
      });
  }, []);

  const filteredUsers = users.filter(user => {
    const fullName = `${user.name.first} ${user.name.last}`.toLowerCase();
    return fullName.includes(search.toLowerCase());
  });

  return (
    <div className="app">
      <h1>ユーザー一覧</h1>
      <input
        type="text"
        placeholder="名前で検索"
        value={search}
        onChange={(e) => setSearch(e.target.value)}
      />

      <ul className="user-list">
        {filteredUsers.length > 0 ? (
          filteredUsers.map((user, index) => (
            <li key={index} className="user-card">
              <img src={user.picture.medium} alt="ユーザー画像" />
              <div>
                <strong>{user.name.first} {user.name.last}</strong><br />
                <small>{user.email}</small>
              </div>
            </li>
          ))
        ) : (
          <li>該当するユーザーはいません。</li>
        )}
      </ul>
    </div>
  );
}

export default App;

スタイル(App.css)

以下のようにスタイルファイルも整えておくと、UIが見やすくなります。

.app {
  max-width: 800px;
  margin: 0 auto;
  padding: 2rem;
  font-family: sans-serif;
}

input {
  width: 100%;
  padding: 0.5rem;
  margin-bottom: 1rem;
}

.user-list {
  list-style: none;
  padding: 0;
}

.user-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem;
  margin-bottom: 0.5rem;
  border: 1px solid #ddd;
  background-color: #fff;
}

解説:React的な書き方のポイント

  • useState()
    userssearchという2つの状態(state)を定義し、それぞれユーザー一覧と検索ワードを管理します。
  • useEffect()
    コンポーネントの初回マウント時に一度だけAPI通信を実行するために使用します(第二引数に空配列を渡す)。
  • .map()
    配列の各ユーザーをループして、JSXでリストを生成します。keyにはindexなどユニークな値を設定。
  • 状態が変わると再レンダリング
    searchの値が更新されるたびに、再レンダリングが走り、表示が即座に更新されます。

よくある初心者ミス

  • useEffect内で非同期処理を直接asyncにしてしまう
    → 解決法:関数を定義してその中でfetchする(またはthenを使う)
  • .map()keyを付け忘れる
    → コンソールに警告が出るので、ユニークな値をkeyに設定
  • 入力フィールドが制御されていない
    valueonChangeのセットが必須

🔗 参考:React公式ドキュメント(useState/useEffect)


まとめ

今回のユーザー一覧アプリの実装を通じて、以下のReactの重要要素を体験できました:

  • 状態管理(useState)
  • ライフサイクル処理(useEffect)
  • フィルター処理によるインタラクション
  • JSXとコンポーネントによるUI構築

このように、Vanilla JSと比べてコードが整理され、保守性の高い設計が自然に実現できるのがReactの魅力です。

次回は、Reactのコンポーネント分割を学びながら、リストや検索バーをパーツ化して再利用可能な構造へリファクタリングする手法を紹介します。


次回予告

Reactのコンポーネント設計 ― UIを分割・整理して再利用性を高める方法

コメント

タイトルとURLをコピーしました