React

React練習問題

答えを見る前に手を動かし、Reactのデータの流れを身につけましょう。

React入門の講座一覧

01

State問題:カウンター

「+1」「-1」「リセット」ボタンを作り、0未満にならないカウンターを実装してください。答えでは関数形式のstate更新を使います。

解答例と実行結果
解答例JSX
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);
  return (<>
    <p>{count}</p>
    <button onClick={() => setCount(c => Math.max(0, c - 1))}>-1</button>
    <button onClick={() => setCount(c => c + 1)}>+1</button>
    <button onClick={() => setCount(0)}>リセット</button>
  </>);
}
操作結果OUTPUT
初期: 0 → +1 → 1 → -1 → 0
02

フォーム問題:Todo

入力した内容を追加し、完了ボタンで取り消し線を切り替え、削除ボタンで消してください。空入力は追加しません。

解答例と実行結果
解答例JSX
function addTodo(event) {
  event.preventDefault();
  const value = text.trim();
  if (value === '') return;
  setTodos(current => [...current,
    { id: crypto.randomUUID(), text: value, done: false }]);
  setText('');
}

function toggle(id) {
  setTodos(current => current.map(todo =>
    todo.id === id ? { ...todo, done: !todo.done } : todo));
}
操作結果OUTPUT
Reactを学ぶ → 追加
Reactを学ぶ → 完了
表示: Reactを学ぶ(取り消し線)
03

Effect問題:通信状態

API通信を「読み込み中」「成功」「失敗」の3状態で表示してください。Effectのcleanupで通信を中断できるようにします。

解答例と確認ポイント
解答例JSX
import { useEffect, useState } from 'react';

useEffect(() => {
  const controller = new AbortController();
  setStatus('loading');
  fetch('/api/items', { signal: controller.signal })
    .then(response => {
      if (response.ok === false) throw new Error('HTTPエラー');
      return response.json();
    })
    .then(items => { setItems(items); setStatus('success'); })
    .catch(error => { if (error.name !== 'AbortError') setStatus('error'); });
  return () => controller.abort();
}, []);

確認例:開始直後は「読み込み中」、成功時は一覧、サーバー停止時は「取得できませんでした」を表示します。

04

Reducer問題:買い物かご

商品追加、数量変更、全削除の3つのactionを持つReducerを作ってください。合計金額はstateへ重複保存せず、itemsから計算します。

解答例と実行結果
ReducerJSX
function cartReducer(state, action) {
  switch (action.type) {
    case 'add': return [...state, action.item];
    case 'clear': return [];
    case 'remove': return state.filter(item => item.id !== action.id);
    default: return state;
  }
}

const total = items.reduce((sum, item) => sum + item.price, 0);
実行結果OUTPUT
ノート 300円を追加 → 合計: 300円
ペン 120円を追加 → 合計: 420円
全削除 → 合計: 0円
05

発展課題:読書記録

タイトル、著者、読了状態を持つ読書記録アプリを作りましょう。登録・検索・完了切り替え・削除・localStorage保存を実装し、次の点を確認します。

  • フォーム入力はcontrolled componentになっているか
  • リストのkeyに固有IDを使っているか
  • 検索結果をEffectではなく計算値として作っているか
  • localStorageの読み書きをEffectで同期しているか
  • 空データ、長いタイトル、保存失敗を考慮しているか

実装できたら、TypeScriptでデータ型を付け、Next.jsのページへ移してみましょう。コードを完成させることだけでなく、stateの所有者とデータの流れを説明できることが目標です。