ボタンで更新
クリックで 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 に入るので、同じ回の中では変わりません。確認したいときは、画面に出して目で見るのが確実です。
演習
いいねボタンと取り消しボタンを付けて、数が増減するようにします。