Reactを触る際、かなりの高確率でuseStateを使うと思います。
use〇〇系はReactに多くありますが、useStateの他にもうひとつ便利なのがuseRefです。
コードレビューで「ここ、useStateじゃなくてuseRefでも良いのでは?」と指摘を受けたことをきっかけに、
「useRefはuseStateとどのように違うのか?」と疑問に思い、整理してみました。
useRefは、DOM要素への参照や値の保持に使われるフックですが、
本記事では、値の保持という観点でuseStateとの違いを整理します!
useRefとは?
useRefは、再レンダリングを発生させずに値を保持できるReactフックです。
useStateは、値を保持しつつ、その値をUIに反映するためによく使われます。
例えば入力フォームのように、「状態が変わると画面も変わる」ケースです。
一方useRefは、値を保持できる点では同じですが、値を更新しても再レンダリングが発生しないという特徴があります。
useStateとの違い
ざっくり整理すると以下の通りです。
useState
→ 値が変わると再レンダリングされる(UIに影響する状態)
useRef
→ 値を保持できるが、更新しても再レンダリングされない(UIに影響しない値)
判断基準
UIを更新したいかどうかで考えると分かりやすいです。
UIを更新したい?
→ Yes → useState
→ No → useRef
ざっくりはこの理解で問題なさそうです。
もう少し正確に言えば、
UIに使わない
かつ、変更しても再レンダリング不要
この2つを満たすならuseRefが適しています。
useRefの使いどころ
業務では、投稿記事の公開状態が変更されたときにアラートを出す処理を書いていました。
具体的には、「公開 → 下書き」に変更されたときのみアラートを表示したいケースです。
このように「前回から特定の変更があったか」を検知するために、最初はprevStatusというuseStateを追加していました。
ですがこの場合、前回の値(prevStatus)は条件分岐にしか使っておらず、UIに影響しないため、useRefで保持することができたのです。
例
const [status, setStatus] = useState("public");
const prevStatus = useRef(status);
useEffect(() => {
if (prevStatus.current === "public" && status === "draft") {
alert("記事は非公開になります");
}
prevStatus.current = status;
}, [status]);
このように、状態そのものはuseStateで管理しつつ、前回の値のような補助的なデータはuseRefで持つ、という使い分けができます。
まとめ
これまで値の保持はuseStateで行うものだと思っていましたが、useRefという選択肢を知ることで、使い分けの重要性を理解できました。
それぞれの役割を意識して適材適所に使うことが、より適切な設計につながると感じています。