はじめに
React の開発で変数を扱うときによく出てくる、 useState
, useRef
, useMemo
。
基本的には useState
を使うことが多いですが、コードが複雑になってくると使い分けた方がより良いケースというのも増えてきます。
最近ちょうど使い分けを意識する状況がいくつかあったので、改めて学び直してみることにしました。
この記事では、これらの Hook の特徴を整理し、具体的な使い方や実践例を紹介します。
対象読者
-
React を既に使ったことがある人
基本的な概念は理解しており、次のステップに進みたい方。 -
React の効率的なコード設計を学びたい人
より複雑なアプリケーションでパフォーマンスを向上させたい方。 -
React Hooks の実践的な使い分けを知りたい人
特定のシチュエーションで、どの Hook を使えばよいか迷ったことがある方。
1. useState
の特徴と具体例
主な特徴
useState
は、コンポーネントに state変数 を追加するための Hook です。
コンポーネント内で値(状態)を管理 し、管理する値が変化するとコンポーネントが再レンダリングされ、UI に反映されます。
具体例: ボタンをクリックしたときにカウントアップする
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
補足: 不適切な使用ケース
-
頻繁に変化する値(例: マウス座標やスクロール位置)の管理
再レンダリングが多発し、パフォーマンスが低下します。この場合はuseRef
を使用するのが適切です。
2. useRef
の特徴と具体例
主な特徴
useRef
は、レンダー時には不要な値を参照するための Hook です。
状態に影響を与えない値や DOM 要素を参照するために用いられ、値が変更されても再レンダリングは発生しません。
具体例: テキスト入力欄にフォーカスを当てる
import { useRef } from 'react';
function InputFocus() {
const inputRef = useRef<HTMLInputElement>(null);
const handleFocus = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
return (
<div>
<input ref={inputRef} type="text" placeholder="ここに入力" />
<button onClick={handleFocus}>フォーカスを当てる</button>
</div>
);
}
補足: 不適切な使用ケース
-
UI 表示に必要な値の管理
useRef
は再レンダリングをトリガーしないため、UI に影響を与える値(例: カウンターの状態)を管理するには不適切です。その場合はuseState
を使用してください。
3. useMemo
の特徴と具体例
主な特徴
useMemo
は、レンダー間で計算結果をキャッシュするための Hook です。
計算コストの高い処理をキャッシュし、効率化するための依存配列が変わらない限り再計算をスキップします。
具体例: 検索クエリに応じてリストをフィルタリング
import { useState, useMemo } from 'react';
function FilterList({ items }: { items: string[] }) {
const [query, setQuery] = useState('');
const filteredItems = useMemo(() => {
console.log('フィルタリング処理が実行されました');
return items.filter(item => item.includes(query));
}, [items, query]);
return (
<div>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="検索"
/>
<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
補足: 不適切な使用ケース
-
計算コストが低い処理のキャッシュ
単純な処理(例: 配列の長さを計算するなど)にuseMemo
を使うと、かえってコードが冗長になり可読性が低下します。 -
値の更新が
useMemo
の範囲外で必要な場合
useMemo
はキャッシュ専用の仕組みであり、値を動的に更新する仕組みはありません。そのため、値の更新をリアクティブに管理したい場合はuseState
を使用する必要があります。
使い分けのポイントまとめ
ここまでの説明をまとめました。
Hook | 適切な用途 | 不適切な用途 |
---|---|---|
useState |
UI に影響を与える状態の管理 | 再レンダリング不要な値や頻繁な更新が必要な値 |
useRef |
値の参照や DOM 要素の操作 | UI 表示に必要な値の管理 |
useMemo |
計算コストの高い処理のキャッシュ | コストが低い処理、または値の更新が必要な場合 |
使い分けを考える上で「適切な用途」を押さえておくことは前提として大事ですが、「不適切な用途」にあたる「どんな時は使えないのか、なぜならば...」を把握することも、より納得した選択をとるために大事だなと思います。
終わりに
Hook の違いがイマイチ理解できてないな...という自分のモヤモヤを出発点に、今回の記事を作ってみましたが、いかがだったでしょうか?
私は、理解が特に足りていなかった useRef
と、それぞれの不適切な使用シーンを整理できたことで、今後実装していく上での判断基準がより明確になったな。という収穫を感じました。
あなたにとっても、何か役立つ要素があったら幸いです。
ここまで読んでいただき、ありがとうございました!