React は UI を作るライブラリですが、HTML などとは違って単に見た目をマークアップするだけのものではありません。先にHTML を触っていた私にとってはその点が少し難しかった記憶があります。
今回は React のフックである useState
についてまとめていきます。
▼ React の基本を復習したい方はこちらもご覧ください
state とは
日本語に直訳すると「状態」ですね。
公式ドキュメント によると、コンポーネントの「記憶」 のことだそうです。
例えばショッピングサイトを React で構築したとしましょう。
コンポーネントはユーザーの操作によって画面に表示されるものを更新するでしょう。検索バーに商品名が打ち込まれれば検索結果のページを表示し、ページの下にある「次へ」ボタンが押されると次のページを表示します。「カートに入れる」を押されればカートに入っている商品の個数を表すアイコンを表示する必要がありますね。
この場合、React のコンポーネントは「検索ワード」「現在の商品ページ」「カートに入った商品の個数」を記憶しているということになります。
コンポーネントが保持していないといけない値 = state という感じでしょうか。
useState
とは
React で state を管理するためのフックです。
▼ フックってなに? と思った方はこちらもご覧ください。
state を管理したいだけなら、一見ただ変数を作って値を保存すればいいだけのような気もします。しかし以下の理由でうまくいきません。
- React が再レンダリング行った際に値が失われる
- 変数の値が変更されてもレンダリングは起こらないため、 state を変更しても反映されない、という状況になる
つまり state を使うためには、
- 再レンダリングされても値が失われない
- 再レンダリングのトリガーになる
という2つの条件が必要であり、それらを叶えてくれるのが useState
というわけです。
useState
は state を保存し、さらに state setter function(ステートを設定し直す関数)を作ります。 state setter function が動作することで再レンダリングが起きます。
useState
の使い方
import { useState } from 'react';
import { sculptureList } from './data.js';
export default function Gallery() {
const [index, setIndex] = useState(0);
function handleClick() {
setIndex(index + 1);
}
let sculpture = sculptureList[index];
return (
<>
<button onClick={handleClick}>
Next
</button>
<h2>
<i>{sculpture.name} </i>
by {sculpture.artist}
</h2>
<h3>
({index + 1} of {sculptureList.length})
</h3>
<img
src={sculpture.url}
alt={sculpture.alt}
/>
<p>
{sculpture.description}
</p>
</>
);
}
// 引用: https://beta.reactjs.org/learn/state-a-components-memory
useState
をはじめとするフックはコンポーネントの一番上で呼び出す必要があります。ドキュメントによるとファイルの先頭でモジュールをインポートするようなものだそうです。
useState
を使うということはコンポーネントに「この値を覚えておいてね」と伝えることです。
const [index, setIndex] = useState(0);
名前は [値, set値]
とするのが一般的です。一般的な命名規則に沿っておけばまず混乱は招かないでしょう。
useState
が受け取っている引数は 初期値 です。この例だと 0
ですね。 index
の値は初期状態だと 0
になるということです。
複数の state を持たせる
複数の state を持たせることもできます。
export default function Gallery() {
const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);
function handleNextClick() {
setIndex(index + 1);
}
function handleMoreClick() {
setShowMore(!showMore);
}
let sculpture = sculptureList[index];
return (
<>
<button onClick={handleNextClick}>
Next
</button>
<h2>
<i>{sculpture.name} </i>
by {sculpture.artist}
</h2>
<h3>
({index + 1} of {sculptureList.length})
</h3>
<button onClick={handleMoreClick}>
{showMore ? 'Hide' : 'Show'} details
</button>
{showMore && <p>{sculpture.description}</p>}
<img
src={sculpture.url}
alt={sculpture.alt}
/>
</>
);
}
// 参考: https://beta.reactjs.org/learn/state-a-components-memory
ただし2つの state を同時に変更している場合が多いな…と思ったら、1つにまとめることを検討した方がいいでしょう。
state は独立している
例えば同じコンポーネントを2カ所でレンダリングしている場合、それぞれの state は別々に保存されます。
import Gallery from './Gallery.js';
export default function Page() {
return (
<div className="Page">
<Gallery />
<Gallery />
</div>
);
}
// 引用: https://beta.reactjs.org/learn/state-a-components-memory
スクショを撮影した State: A Component's Memory で実際に触れるので試してみてください。
まとめ
- state はコンポーネントの記憶であり、コンポーネントが保持していないといけない値
-
useState
は React で state を管理するためのフック -
useState
が受け取っている引数は初期値 -
useState
を複数回使って複数の state を持たせることもできる - state は独立しているので同じコンポーネントを2カ所でレンダリングしている場合、それぞれの state は別々に保存される