useStateってなに
ReactにはHookと呼ばれる関数いくつか用意されている。
よく見るのはuseState
とuseEffect
だと思う
今回はuseState
について理解したい。
useState
はstate変数を定義できるらしい
早速わからない単語が出てきた
state変数という言葉は聞いたことない
state変数とローカル変数
普通に使う変数とstate変数が何が違うのかわからなかったので
とりあえず公式ドキュメントに目を通してみた。
太文字で2つの重要そうなことが書いてあった
ローカル変数はレンダー間で保持されません
ローカル変数の変更は、レンダーをトリガしません
つまりどういうことか
export default function App() {
let count:number = 0
function handleClick() {
count = count + 1;
console.log(index)//0,1,2,3....
}
return (
<>
<div>{count}</div>
<button onClick={handleClick}>
increment
</button>
</>
);
}
これはbuttonをクリックしたらcount変数に1を足す。それを表示している
しかしこれを実行してbuttonをクリックしても表示されるのは0の文字だけ
console.logの結果はしっかり加算されています。
前述の公式ドキュメント通りの結果です。
ローカル変数の変更は、レンダーをトリガしません
じゃあどうするのかってなった時にstate変数の出番ということです。
正しく動作するように書き直すと
import { useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count => count + 1)
console.log(count); // 1, 2, 3...
}
return (
<>
<div>{count}</div>
<button onClick={handleClick}>
increment
</button>
</>
);
}
useState()
の引数にはstate変数を初期化したい値を入れます。
[count, setCount]
count
がstate変数です
setCount
がstate変数の値を変更する関数です
setCount(count => count + 1)
ここは
setCount(count + 1)
これでもいいけど、コールバックで書いた方が推奨される。
非同期の処理のなかでsetCount(count + 1)
こちらの書き方をすると上手く動かなかった。
重要そうなもう一つの文言
ローカル変数はレンダー間で保持されません
これはどういうことなのか
ローカル変数はレンダー間で保持されません
そもそもレンダーされるのはどのタイミング?
- state変数が変わった時
- 親コンポーネントが再レンダーされたとき
- Propsが変わった時
以上のタイミングでレンダーされるようです。
つまりレンダー間で保持されないということはstate変数が変わったらローカル変数は初期化されるってこと
import { useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
let localVar = 0;
function handleClick() {
setCount(count + 1)
localVar = localVar + 1
console.log(localVar); // 1, 1, 1...
}
return (
<>
<div>{count}</div>
<button onClick={handleClick}>
increment
</button>
</>
);
}
先ほどuseStateで使ったコードにlocalVar
変数を追加して同時にインクリメントしてみました。
するとconsoleの出力には1がずっと表示されます。
再レンダーされる際にlocalVar
変数が初期化されているのが確認できます
Classに書いたメンバ変数みたいだと思いました。
まとめ
フロントエンドフレームワークはVueしか触ったことありませんでしたが、Vueでも値を変更したのにDOMに反映されてない、、、と苦しんだ覚えがあります。
そこらへんが、Reactではすんなりと理解できた気がします。VueをやってたからなのかReactがわかりやすいのかわかりませんが、成長した気になれました。