useRefとは?

useRef
は React の フック(Hook) の一つで、次のような用途で使われます。
✅ ① コンポーネントが再レンダリングされても値を保持する(state
とは違い、変更しても再レンダリングしない)
✅ ② DOM(HTML要素)を直接操作する(document.querySelector()
のような処理を React
で実装)
useRefの使い方

実際にコードを書いて見ていきましょう。
アプリ「useref-app」を作成しFocusInputコンポーネントを作ります。
npx create-next-app@latest useref-app
app/components/focusInput.js
"use client";
import { useEffect, useRef, useState } from "react";
function FocusInput() {
const inputRef = useRef(null);
const [count, setCount] = useState(0);
// ✅ コンポーネントがマウントまたは再レンダリングされるたびに alert を表示
useEffect(() => {
alert("コンポーネントがレンダリングされました!");
});
const handleFocus = () => {
inputRef.current.focus();
inputRef.current.value = "フォーカスされました!"; // ✅ `inputRef` を変更
};
return (
<div>
<input ref={inputRef} type="text" placeholder="Type here..." />
<button onClick={handleFocus}>フォーカスを当てる(useRef変更)</button>
<button onClick={() => setCount(count + 1)}>カウント増加(useState変更)</button>
<p>カウント: {count}</p>
</div>
);
}
export default FocusInput;
app/page.js
import Image from "next/image";
import FocusInput from "./components/focusInput";
export default function Home() {
return (
<FocusInput />
);
}


開発サーバーを作り、画面を確認します。
npm run dev
最初に「コンポーネントがレンダリングされました!」とアラートが表示されます。

次に「フォーカスを当てる」をクリックしてもアラートは出ません。

「カウント増加」をクリックすると

アラートが出ます。

このようにuseStateは更新されるごとにコンポーネントが再レンダリングされるのに対して、useRefは更新しても再レンダリングされないことがわかります。
コード解説
コードを解説していきます。
クライアントコンポーネントの宣言、必要な機能のインポートをしています。
"use client";
import { useEffect, useRef, useState } from "react";
使用するstateとrefを設定しています。
function FocusInput() {
const inputRef = useRef(null);
const [count, setCount] = useState(0);
useEffectを使ってレンダリングされたときにアラートが出るようにしています。
useEffect(() => {
alert("コンポーネントがレンダリングされました!");
});
ここでは第二引数の[]を省略することで、レンダリングされる度に動くようにしています。
レンダリングされる度には動く処理であればuseEffectを使わずに直にalertを記述してもよさそうなものですが、実際これはエラーがでます。理由は後述します。
「フォーカスを当てる」ボタンのクリックイベントのイベントハンドラーを記述しています。
const handleFocus = () => {
inputRef.current.focus();
inputRef.current.value = "フォーカスされました!"; // ✅ `inputRef` を変更
};
ここではinputRefにフォーカスを当てる処理とvalueの値を「フォーカスされました!」に設定する処理を定義しています。
続けて戻り値のJSXです。
return (
<div>
<input ref={inputRef} type="text" placeholder="Type here..." />
<button onClick={handleFocus}>フォーカスを当てる(useRef変更)</button>
<button onClick={() => setCount(count + 1)}>カウント増加(useState変更)</button>
<p>カウント: {count}</p>
</div>
);
注目すべきなのは下記です。
<input ref={inputRef} type="text" placeholder="Type here..." />
このように、タグのrefプロパティにuseRefの値を設定することで、このタグをDOM操作できるようにしています。
「フォーカスを当てる」ボタンタグのクリックイベントでこのinputタグをDOM操作できるようにしているわけです。
<button onClick={handleFocus}>フォーカスを当てる(useRef変更)</button>
このように、useRefはDOM操作をするときに使用します。
副作用について
今回のコードの中で、
useEffect(() => {
alert("コンポーネントがレンダリングされました!");
});
という、alertの処理をわざわざuseEffect内に実装する記述がありました。
たとえば、
alert("コンポーネントがレンダリングされました!");
というように、コンポーネント内に直接記述するとエラーが発生します。
これはなぜかというと、このalertの記述が「副作用」であるためです。
副作用ってなんやねん?
React のコンポーネントは基本的に 「入力 → 出力」 という流れで動くシンプルなもの。
たとえば、次のようなコードは 「純粋な処理」 です。
✅ 純粋な処理(副作用なし)
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
この処理は「何かを変更したり影響を与えたりしない」ので、スッキリしてる!
💩 副作用のある処理
でも、もしこの関数の中で 「コンソールにログを出す」 とか 「画面のタイトルを変える」 みたいなことをすると…
それは 「副作用(Side Effect)」 になります!
function addWithEffect(a, b) {
console.log("足し算が実行されました!"); // 💩 これは副作用
document.title = `合計: ${a + b}`; // 💩 これも副作用
return a + b;
}
console.log(addWithEffect(2, 3)); // 5
🚨 「足し算をするだけのはずなのに、コンソール出力やタイトル変更をしてる!」
🚨 「本来の目的(足し算)以外のことをしてる!」
🚨 これが useEffect
で管理すべき「副作用」なのだ!
React における副作用
React では、コンポーネントの役割は 「UI を描画すること」。
でも、時々 「コンポーネントの外の世界」に影響を与えないといけないことがあります。(副作用)
✅ API リクエスト | サーバーからデータを取得する(fetch など) |
✅ イベントリスナー | window.addEventListener("scroll", ...) を設定 |
✅ タイマー処理 | setTimeout や setInterval を使う |
こういった処理はuseEffectで管理することになっています。
少しイメージしづらいですが、ルールとして覚えておきましょう。
コメント