― 状態・イベント・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()
users
とsearch
という2つの状態(state)を定義し、それぞれユーザー一覧と検索ワードを管理します。 - useEffect()
コンポーネントの初回マウント時に一度だけAPI通信を実行するために使用します(第二引数に空配列を渡す)。 - .map()
配列の各ユーザーをループして、JSXでリストを生成します。key
にはindexなどユニークな値を設定。 - 状態が変わると再レンダリング
search
の値が更新されるたびに、再レンダリングが走り、表示が即座に更新されます。
よくある初心者ミス
useEffect
内で非同期処理を直接async
にしてしまう
→ 解決法:関数を定義してその中でfetchする(またはthen
を使う).map()
にkey
を付け忘れる
→ コンソールに警告が出るので、ユニークな値をkeyに設定- 入力フィールドが制御されていない
→value
とonChange
のセットが必須
まとめ
今回のユーザー一覧アプリの実装を通じて、以下のReactの重要要素を体験できました:
- 状態管理(useState)
- ライフサイクル処理(useEffect)
- フィルター処理によるインタラクション
- JSXとコンポーネントによるUI構築
このように、Vanilla JSと比べてコードが整理され、保守性の高い設計が自然に実現できるのがReactの魅力です。
次回は、Reactのコンポーネント分割を学びながら、リストや検索バーをパーツ化して再利用可能な構造へリファクタリングする手法を紹介します。
次回予告
Reactのコンポーネント設計 ― UIを分割・整理して再利用性を高める方法
コメント