ボタンで更新

クリックで state を変える

state を宣言できたので、次はユーザーの操作で値を変えます。ボタンを押したときの処理は onClick に関数を渡して書きます。

import { useState } from "react"; export default function App() { const [likes, setLikes] = useState(0); function handleLike() { setLikes(likes + 1); } return ( <div> <p>いいね {likes}</p> <button onClick={handleLike}>いいね</button> </div> ); }

押すと handleLike が動き、setLikes が新しい値を React に渡し、React が App を呼び直して新しい画面を作ります。

関数を渡す、呼ばない

一番多い間違いがこれです。

<button onClick={handleLike()}>いいね</button>

handleLike() と丸かっこを付けると、描画のたびにその場で実行されてしまいます。押していないのに setLikes が呼ばれ、それがまた描画を呼び、また実行され、と止まらなくなります。onClick には関数そのものを渡すので onClick={handleLike} です。

引数を渡したいときだけ、アロー関数で包みます。

<button onClick={() => setLikes(likes + 5)}>まとめて 5 いいね</button>

これは「押されたときに実行する関数」を渡しているので問題ありません。

前の値から計算する

setLikes(likes + 1) は今の likes を読んで 1 を足しています。ほとんどの場面ではこれで動きますが、1 回のクリックで 2 回続けて呼ぶと期待どおりになりません。

function handleDouble() { setLikes(likes + 1); setLikes(likes + 1); }

likes が 0 のとき、2 行とも「0 + 1」を計算するので結果は 1 です。2 にはなりません。今回の描画の likes は途中で書きかわらないからです。

確実に前の値から積み上げたいときは、更新関数に 関数 を渡します。

function handleDouble() { setLikes((prev) => prev + 1); setLikes((prev) => prev + 1); }

prev には React が「その時点の最新の値」を入れてくれるので、こちらは 2 になります。前の値をもとに更新するときは、この形を選んでおくと安全です。

減らす、戻す

更新関数は何度でも使えます。取り消しなら引き算、リセットなら初期値を渡すだけです。

<button onClick={() => setLikes(likes - 1)}>取り消し</button> <button onClick={() => setLikes(0)}>リセット</button>

つまずきどころ

setLikes を呼んだ直後に console.log(likes) を書いても、古い値が出ます。新しい値は次の描画で作られる likes に入るので、同じ回の中では変わりません。確認したいときは、画面に出して目で見るのが確実です。

演習

いいねボタンと取り消しボタンを付けて、数が増減するようにします。

ヒント

App.jsx
App.jsx
プレビュー

できているか

  • はじめは「いいね 0」と表示されている
  • いいねボタンを 2 回押すと「いいね 2」になる
  • 続けて取り消しボタンを 1 回押すと「いいね 1」に戻る