はじめに
Reactを触って3ヶ月が経とうとしています。大体のことは思い通りにできるようになってきたと思っていたのですが、久しぶりにuseStateでつまづいたのでまとめます。
割と多くの人が遭遇するのかなと思いました
問題
以下のコードのように「いいね数」をボタンで増減できるコードを書きました
今回は「taro」のいいね数だけですが、本来であればハッシュにある全てが1画面に表示されます。
import { useState } from "react";
import "./styles.css";
export default function App() {
const id = "taro";
const [likes, setLikes] = useState({
taro: 0,
hanako: 3
});
const countUp = () => {
likes["taro"] = likes["taro"] + 1;
setLikes(likes);
console.log(likes);
};
return (
<div className="App">
<h1>太郎のいいね数{likes[id]}</h1>
<button onClick={() => countUp()}>+1</button>
</div>
);
}
ここで、ボタンを押したときに表示されたいいね数が1増加すると思ったのですが、なぜかされません。
ログを確認したところlikesの中身は変更されていたようなのでsetStateがうまくいっていないようでした。
#解決方法
こちらの記事を見て原因がわかりました
setStateで変更があったと判断する基準がオブジェクト自体なのでオブジェクトが同じlikesの要素を変えても変更が反映されないようです
そこで以下のように新たなハッシュであるnetArrayを作成して、そこに要素を入れてから代入したところうまく動くようになりました。
import { useState } from "react";
import "./styles.css";
export default function App() {
const id = "taro";
const [likes, setLikes] = useState({
taro: 0,
hanako: 3
});
const countUp = () => {
let newArray = {};
likes.forEach((k, v) => {
if (k === "taro") {
newArray[k] = v + 1;
} else {
newArray[k] = v;
}
});
setLikes(newArray);
};
return (
<div className="App">
<h1>太郎のいいね数{likes[id]}</h1>
<button onClick={() => countUp()}>+1</button>
</div>
);
}
配列でも同じことが起きそうなのでスプレッド展開するなどして別のオブジェクトに値を移してから代入するようにしましょう
おわりに
今回は基本に立ち返ってレンダリングされないトラブルに対処してみました。
もっとハッシュを使った更新でいい方法があるような気もしています。
今回のいいねのようなものはどうやっているのか気になりました
参考