Next.jsで学ぶReact講座 | Reactの基本操作 – ボタンを押すと増えるカウンター

Next.js
スポンサーリンク

このテーマのゴール

ここでやりたいのは、「ボタンを押すと数字が増える」カウンターコンポーネントを通して、React の state とイベント処理の超基本を体で覚えることです。

画面に数字が表示されていて、
「増やす」ボタンを押すたびに 1, 2, 3… と増えていく。
この“ちっちゃい動き”の中に、React の大事な要素が全部詰まっています。

  • 「今の値」を覚えておく state
  • 「ボタンが押された」というイベント
  • 「state が変わると画面が自動で更新される」という仕組み

これを一つずつ、ちゃんとつなげていきます。


まずは完成形のコードを見てみる

シンプルなカウンターコンポーネント

"use client";

import { useState } from "react";

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

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div style={{ padding: "16px", border: "1px solid #e5e7eb", borderRadius: "8px" }}>
      <p style={{ marginBottom: "8px" }}>現在のカウント: {count}</p>
      <button
        onClick={handleClick}
        style={{
          padding: "6px 12px",
          borderRadius: "9999px",
          border: "none",
          backgroundColor: "#3b82f6",
          color: "white",
          cursor: "pointer",
        }}
      >
        1 増やす
      </button>
    </div>
  );
}
TSX
// app/page.tsx
import { Counter } from "./Counter";

export default function Page() {
  return (
    <main style={{ padding: "24px", fontFamily: "system-ui, sans-serif" }}>
      <h1 style={{ fontSize: "22px", marginBottom: "16px" }}>カウンターの例</h1>
      <Counter />
    </main>
  );
}
TSX

画面には「現在のカウント: 0」と表示され、
ボタンを押すたびに 1, 2, 3… と増えていきます。


useState で「今の値」を覚えておく

state とは「変わる値」を覚えておくための箱

この行が、今回の心臓部です。

const [count, setCount] = useState(0);
TSX

ここでやっていることを、かみ砕いて説明します。

  • count は「今のカウントの値」を表す変数
  • setCount は「count を新しい値に更新するための関数」
  • useState(0) は「初期値 0 で state を作る」という意味

イメージとしては、

「最初は count = 0 からスタートして、
setCount(新しい値) を呼ぶたびに count が変わる。
そして、count が変わると React が自動で画面を描き直してくれる」

という感じです。

普通の変数(let count = 0 など)と違うのは、
useState で作った値は、変わったときに画面も一緒に更新されるという点です。

JSX の中で state を表示する

この行も重要です。

<p>現在のカウント: {count}</p>
TSX

{count} と書くことで、「今の count の値」を画面に埋め込んでいます。

  • 最初は count = 0 なので「現在のカウント: 0」と表示される
  • setCount(1) が呼ばれると、count = 1 になり、「現在のカウント: 1」と表示が変わる

ここであなたがやっているのは「count を変えること」だけ。
「画面を更新する」処理は、全部 React が勝手にやってくれます。


ボタンが押されたときに count を増やす

onClick とイベントハンドラ

ボタンの部分を見てみましょう。

<button onClick={handleClick}>1 増やす</button>
TSX

onClick={handleClick} は、

「このボタンがクリックされたら、handleClick という関数を実行してね」

という意味です。

その handleClick の中身がこれ。

function handleClick() {
  setCount(count + 1);
}
TSX

やっていることはシンプルで、

  • 今の count に 1 を足した値を
  • setCount に渡している

だけです。

例えば、今 count = 3 なら、
setCount(3 + 1)setCount(4) が呼ばれ、
次のレンダリングでは count = 4 になり、画面には「現在のカウント: 4」と表示されます。

「ボタンを押す → state を変える → 画面が変わる」の流れ

このカウンターで起きていることを、流れで整理するとこうなります。

ユーザーがボタンをクリックする
onClick に指定した handleClick が呼ばれる
handleClick の中で setCount(count + 1) が実行される
count の値が変わる
React が「お、state 変わったな」と気づいて、コンポーネントをもう一度描画する
新しい count の値が画面に反映される

この「イベント → state 更新 → 再描画」という流れが、
React のインタラクティブな UI の基本パターンです。


もう一歩:初期値を props で変えられるようにする

「最初の値だけ変えたい」パターン

少しだけレベルを上げて、「カウンターの初期値を外から変えられるようにする」パターンも見てみましょう。

type CounterProps = {
  initialValue?: number; // 省略可能
};

export function Counter({ initialValue = 0 }: CounterProps) {
  const [count, setCount] = useState(initialValue);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <p>現在のカウント: {count}</p>
      <button onClick={handleClick}>1 増やす</button>
    </div>
  );
}
TSX

使う側は、こう書けます。

<Counter />              // 0 からスタート
<Counter initialValue={5} />  // 5 からスタート
<Counter initialValue={10} /> // 10 からスタート
TSX

ここでのポイントは、

  • initialValue を props として受け取っている
  • 受け取らなかった場合は = 0 でデフォルト値を 0 にしている
  • useState(initialValue) で「最初の count の値」を変えられるようにしている

というところです。

これで、「同じカウンターコンポーネントを、違う初期値で何度も使う」という再利用性が一気に上がります。


まとめ:このカウンターからつかんでほしいこと

この「ボタンを押すと増えるカウンターコンポーネント」で、絶対に持ち帰ってほしいのはこの感覚です。

useState は「変わる値」を覚えておくための箱で、[値, 更新関数] のペアを返してくれる
イベント(onClick)で「いつ state を変えるか」を決め、setCount で値を更新する
state が変わると、React が自動で画面を描き直してくれるので、自分で DOM をいじる必要はない

ここが腑に落ちると、

  • いいねボタンのカウント
  • カート内の商品数
  • ステップ形式フォームの現在ステップ

みたいな「ユーザーの操作に応じて変わる UI」を、自信を持って書けるようになります。

もしよければ、このカウンターに「減らすボタン」や「リセットボタン」を足してみてください。
setCount(count - 1)setCount(0) をどう組み合わせるか考えるだけで、state とイベントの理解が一段深くなります。

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