<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
	<id>http://mochiuwiki.e2.valueserver.jp/index.php?action=history&amp;feed=atom&amp;title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useRef</id>
	<title>Reactの基礎 - useRef - 版の履歴</title>
	<link rel="self" type="application/atom+xml" href="http://mochiuwiki.e2.valueserver.jp/index.php?action=history&amp;feed=atom&amp;title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useRef"/>
	<link rel="alternate" type="text/html" href="http://mochiuwiki.e2.valueserver.jp/index.php?title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useRef&amp;action=history"/>
	<updated>2026-07-01T01:28:32Z</updated>
	<subtitle>このウィキのこのページに関する変更履歴</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://mochiuwiki.e2.valueserver.jp/index.php?title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useRef&amp;diff=14543&amp;oldid=prev</id>
		<title>Wiki: ページの作成:「== 概要 == &lt;code&gt;useRef&lt;/code&gt; は、レンダリングに必要のない値への参照を保持するためのHookである。&lt;br&gt; 基本構文は &lt;code&gt;const ref = useRef(initialValue)&lt;/code&gt; であり、&lt;code&gt;{ current: T }&lt;/code&gt; 構造のRefObjectを返す。&lt;br&gt; &lt;br&gt; &lt;u&gt;&lt;code&gt;useRef&lt;/code&gt; の最大の特徴は、&lt;code&gt;ref.current&lt;/code&gt; の値を変更しても再レンダリングが発生しない点である。&lt;/u&gt;&lt;br&gt; これは値の変更があるた…」</title>
		<link rel="alternate" type="text/html" href="http://mochiuwiki.e2.valueserver.jp/index.php?title=React%E3%81%AE%E5%9F%BA%E7%A4%8E_-_useRef&amp;diff=14543&amp;oldid=prev"/>
		<updated>2026-03-06T19:36:10Z</updated>

		<summary type="html">&lt;p&gt;ページの作成:「== 概要 == &amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; は、レンダリングに必要のない値への参照を保持するためのHookである。&amp;lt;br&amp;gt; 基本構文は &amp;lt;code&amp;gt;const ref = useRef(initialValue)&amp;lt;/code&amp;gt; であり、&amp;lt;code&amp;gt;{ current: T }&amp;lt;/code&amp;gt; 構造のRefObjectを返す。&amp;lt;br&amp;gt; &amp;lt;br&amp;gt; &amp;lt;u&amp;gt;&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; の最大の特徴は、&amp;lt;code&amp;gt;ref.current&amp;lt;/code&amp;gt; の値を変更しても再レンダリングが発生しない点である。&amp;lt;/u&amp;gt;&amp;lt;br&amp;gt; これは値の変更があるた…」&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新規ページ&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== 概要 ==&lt;br /&gt;
&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; は、レンダリングに必要のない値への参照を保持するためのHookである。&amp;lt;br&amp;gt;&lt;br /&gt;
基本構文は &amp;lt;code&amp;gt;const ref = useRef(initialValue)&amp;lt;/code&amp;gt; であり、&amp;lt;code&amp;gt;{ current: T }&amp;lt;/code&amp;gt; 構造のRefObjectを返す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; の最大の特徴は、&amp;lt;code&amp;gt;ref.current&amp;lt;/code&amp;gt; の値を変更しても再レンダリングが発生しない点である。&amp;lt;/u&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
これは値の変更があるたびにコンポーネントを再描画する &amp;lt;code&amp;gt;useState&amp;lt;/code&amp;gt; とは根本的に異なる動作である。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; の主な用途は以下の2つに大別される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* DOM要素への参照&lt;br /&gt;
*: &amp;lt;code&amp;gt;ref&amp;lt;/code&amp;gt; 属性にRefObjectを渡すことで、DOMノードへの直接アクセスが可能になる。&lt;br /&gt;
*: フォーカス制御、スクロール操作、メディア再生等に利用する。&lt;br /&gt;
* ミュータブルな値の保持&lt;br /&gt;
*: レンダリングをまたいで値を保持し続けるが、画面描画には影響しない。&lt;br /&gt;
*: タイマIDや前回の値、WebSocketインスタンスの保持に利用する。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
TypeScriptでは、&amp;lt;code&amp;gt;useRef&amp;amp;lt;HTMLInputElement&amp;amp;gt;(null)&amp;lt;/code&amp;gt; のように型引数を指定することで、型安全なDOM操作が可能になる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== DOM要素への参照 ==&lt;br /&gt;
ReactではDOM要素を直接操作するために &amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; を使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ref&amp;lt;/code&amp;gt; 属性にRefObjectを渡すことにより、コンポーネントのマウント後に &amp;lt;code&amp;gt;ref.current&amp;lt;/code&amp;gt; からDOMノードへアクセスできる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== TypeScriptでのDOM型指定 ====&lt;br /&gt;
TypeScriptで &amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; を使用する場合、型引数にDOM要素の型を指定する必要がある。&amp;lt;br&amp;gt;&lt;br /&gt;
初期値には &amp;lt;u&amp;gt;null&amp;lt;/u&amp;gt; を指定して、型引数でアクセスするDOM要素の型を明示する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
下表に、よく使用されるDOM要素の型を示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ よく使用されるDOM要素の型&lt;br /&gt;
! 型名 !! 対象要素 !! 使用例&lt;br /&gt;
|-&lt;br /&gt;
| HTMLInputElement || &amp;lt;code&amp;gt;&amp;amp;lt;input&amp;amp;gt;&amp;lt;/code&amp;gt; || テキスト入力、フォーカス制御&lt;br /&gt;
|-&lt;br /&gt;
| HTMLTextAreaElement || &amp;lt;code&amp;gt;&amp;amp;lt;textarea&amp;amp;gt;&amp;lt;/code&amp;gt; || 複数行テキスト入力&lt;br /&gt;
|-&lt;br /&gt;
| HTMLButtonElement || &amp;lt;code&amp;gt;&amp;amp;lt;button&amp;amp;gt;&amp;lt;/code&amp;gt; || ボタン操作&lt;br /&gt;
|-&lt;br /&gt;
| HTMLDivElement || &amp;lt;code&amp;gt;&amp;amp;lt;div&amp;amp;gt;&amp;lt;/code&amp;gt; || スクロール制御、レイアウト操作&lt;br /&gt;
|-&lt;br /&gt;
| HTMLVideoElement || &amp;lt;code&amp;gt;&amp;amp;lt;video&amp;amp;gt;&amp;lt;/code&amp;gt; || 動画再生・一時停止&lt;br /&gt;
|-&lt;br /&gt;
| HTMLCanvasElement || &amp;lt;code&amp;gt;&amp;amp;lt;canvas&amp;amp;gt;&amp;lt;/code&amp;gt; || Canvas描画&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
TypeScriptでの基本的な型指定を以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useRef } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 function MyComponent() {&lt;br /&gt;
    // HTMLInputElement型を指定し、初期値はnull&lt;br /&gt;
    const inputRef = useRef&amp;lt;HTMLInputElement&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    // HTMLDivElement型を指定&lt;br /&gt;
    const divRef = useRef&amp;lt;HTMLDivElement&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    // HTMLVideoElement型を指定&lt;br /&gt;
    const videoRef = useRef&amp;lt;HTMLVideoElement&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;input ref={inputRef} /&amp;gt;&lt;br /&gt;
          &amp;lt;div ref={divRef}&amp;gt;コンテンツ&amp;lt;/div&amp;gt;&lt;br /&gt;
          &amp;lt;video ref={videoRef} src=&amp;quot;video.mp4&amp;quot; /&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== DOM操作の例 ====&lt;br /&gt;
DOM要素への参照を活用した操作例を以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ref.current&amp;lt;/code&amp;gt; が &amp;lt;u&amp;gt;null&amp;lt;/u&amp;gt; になる場合があるため、オプショナルチェーン (&amp;lt;code&amp;gt;?.&amp;lt;/code&amp;gt;) を使用して安全にアクセスする。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* フォーカス制御の例&lt;br /&gt;
*: 以下の例では、ボタンを押下すると入力欄にフォーカスを当てている。&lt;br /&gt;
*: &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useRef } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export default function FocusExample() {&lt;br /&gt;
    const inputRef = useRef&amp;lt;HTMLInputElement&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    const handleFocus = () =&amp;gt; {&lt;br /&gt;
       // オプショナルチェーンで安全にアクセス&lt;br /&gt;
       inputRef.current?.focus();&lt;br /&gt;
    };&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;input ref={inputRef} placeholder=&amp;quot;テキストを入力&amp;quot; /&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handleFocus}&amp;gt;フォーカス&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*: &amp;lt;br&amp;gt;&lt;br /&gt;
* スクロール操作の例&lt;br /&gt;
*: 以下の例では、ボタンを押下すると特定の要素までスクロールしている。&lt;br /&gt;
*: &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useRef } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export default function ScrollExample() {&lt;br /&gt;
    const targetRef = useRef&amp;lt;HTMLDivElement&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    const handleScroll = () =&amp;gt; {&lt;br /&gt;
       targetRef.current?.scrollIntoView({ behavior: &amp;#039;smooth&amp;#039; });&lt;br /&gt;
    };&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handleScroll}&amp;gt;ターゲットへスクロール&amp;lt;/button&amp;gt;&lt;br /&gt;
          &amp;lt;div style={{ height: &amp;#039;200px&amp;#039; }} /&amp;gt;&lt;br /&gt;
          &amp;lt;div ref={targetRef}&amp;gt;ここにスクロールする&amp;lt;/div&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*: &amp;lt;br&amp;gt;&lt;br /&gt;
* メディア再生の例&lt;br /&gt;
*: 以下の例では、動画の再生・一時停止を制御している。&lt;br /&gt;
*: &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useRef } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export default function VideoPlayer() {&lt;br /&gt;
    const videoRef = useRef&amp;lt;HTMLVideoElement&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    const handlePlay = () =&amp;gt; videoRef.current?.play();&lt;br /&gt;
    const handlePause = () =&amp;gt; videoRef.current?.pause();&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;video ref={videoRef} src=&amp;quot;video.mp4&amp;quot; /&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handlePlay}&amp;gt;再生&amp;lt;/button&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handlePause}&amp;gt;一時停止&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== useRefとuseStateの違い ==&lt;br /&gt;
&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; と &amp;lt;code&amp;gt;useState&amp;lt;/code&amp;gt; はどちらも値を保持するが、再レンダリングへの影響とミュータブル性に大きな違いがある。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
下表に、両者の比較を示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ useRefとuseStateの比較&lt;br /&gt;
! 項目 !! useRef !! useState&lt;br /&gt;
|-&lt;br /&gt;
| 再レンダリング || 値を変更しても発生しない。 || 値を変更すると発生する。&lt;br /&gt;
|-&lt;br /&gt;
| ミュータブル性 || &amp;lt;code&amp;gt;ref.current&amp;lt;/code&amp;gt; を直接変更可能 || &amp;lt;code&amp;gt;setState&amp;lt;/code&amp;gt; 関数を経由して変更する。&lt;br /&gt;
|-&lt;br /&gt;
| 読み取り方法 || &amp;lt;code&amp;gt;ref.current&amp;lt;/code&amp;gt; で読み取る。 || 変数名で直接読み取る。&lt;br /&gt;
|-&lt;br /&gt;
| 主な用途 || DOM操作、タイマID、ミュータブルな値 || UIに反映させる状態管理&lt;br /&gt;
|-&lt;br /&gt;
| TypeScript型 || &amp;lt;code&amp;gt;RefObject&amp;amp;lt;T&amp;amp;gt;&amp;lt;/code&amp;gt; または &amp;lt;code&amp;gt;MutableRefObject&amp;amp;lt;T&amp;amp;gt;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;[T, Dispatch&amp;amp;lt;SetStateAction&amp;amp;lt;T&amp;amp;gt;&amp;amp;gt;]&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
両者の動作の違いを確認する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useRef, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export default function Counter() {&lt;br /&gt;
    // useStateの場合 : 値を変更すると再レンダリングが発生する&lt;br /&gt;
    const [stateCount, setStateCount] = useState(0);&lt;br /&gt;
 &lt;br /&gt;
    // useRefの場合 : 値を変更しても再レンダリングは発生しない&lt;br /&gt;
    const refCount = useRef(0);&lt;br /&gt;
 &lt;br /&gt;
    const handleStateIncrement = () =&amp;gt; {&lt;br /&gt;
       setStateCount(stateCount + 1);  // 再レンダリングが発生する&lt;br /&gt;
    };&lt;br /&gt;
 &lt;br /&gt;
    const handleRefIncrement = () =&amp;gt; {&lt;br /&gt;
       refCount.current += 1;  // 再レンダリングは発生しない&lt;br /&gt;
       console.log(&amp;#039;refCount:&amp;#039;, refCount.current);  // コンソールには出力されるが画面は変わらない&lt;br /&gt;
    };&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;p&amp;gt;useState: {stateCount} (画面に反映される)&amp;lt;/p&amp;gt;&lt;br /&gt;
          &amp;lt;p&amp;gt;useRef: 変化しているが画面には反映されない&amp;lt;/p&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handleStateIncrement}&amp;gt;useState + 1&amp;lt;/button&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handleRefIncrement}&amp;gt;useRef + 1&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ミュータブルな値の保持 ==&lt;br /&gt;
&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; はDOMへの参照だけでなく、レンダリングをまたいで値を保持し続けるミュータブルなコンテナとしても使用できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 前回の値の保持 ====&lt;br /&gt;
前回のレンダリング時の値を保持したい場合、&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; を使用したカスタムHookパターンが有効である。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useEffect, useRef } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // usePreviousカスタムHook : 前回の値を返す&lt;br /&gt;
 function usePrevious&amp;lt;T&amp;gt;(value: T): T | undefined {&lt;br /&gt;
    const ref = useRef&amp;lt;T | undefined&amp;gt;(undefined);&lt;br /&gt;
 &lt;br /&gt;
    useEffect(() =&amp;gt; {&lt;br /&gt;
       // エフェクト内で更新することで、レンダリング後に前回の値が保存される&lt;br /&gt;
       ref.current = value;&lt;br /&gt;
    });&lt;br /&gt;
 &lt;br /&gt;
    return ref.current;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 export default function PreviousValueExample() {&lt;br /&gt;
    const [count, setCount] = useState(0);&lt;br /&gt;
    const prevCount = usePrevious(count);&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;p&amp;gt;現在の値: {count}&amp;lt;/p&amp;gt;&lt;br /&gt;
          &amp;lt;p&amp;gt;前回の値: {prevCount}&amp;lt;/p&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;増加&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== タイマIDの保持 ====&lt;br /&gt;
&amp;lt;code&amp;gt;setInterval&amp;lt;/code&amp;gt; や &amp;lt;code&amp;gt;setTimeout&amp;lt;/code&amp;gt; のIDを保持してタイマを管理する場合、&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; が適切である。&amp;lt;br&amp;gt;&lt;br /&gt;
タイマIDはUIの表示には不要であるため、&amp;lt;code&amp;gt;useState&amp;lt;/code&amp;gt; ではなく &amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; を使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useRef, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export default function TimerExample() {&lt;br /&gt;
    const [count, setCount] = useState(0);&lt;br /&gt;
    const intervalIdRef = useRef&amp;lt;number | null&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    const handleStart = () =&amp;gt; {&lt;br /&gt;
       if (intervalIdRef.current !== null) return;  // 既に起動中なら何もしない&lt;br /&gt;
 &lt;br /&gt;
       intervalIdRef.current = window.setInterval(() =&amp;gt; {&lt;br /&gt;
          setCount(prev =&amp;gt; prev + 1);&lt;br /&gt;
       }, 1000);&lt;br /&gt;
    };&lt;br /&gt;
 &lt;br /&gt;
    const handleStop = () =&amp;gt; {&lt;br /&gt;
       if (intervalIdRef.current === null) return;&lt;br /&gt;
 &lt;br /&gt;
       clearInterval(intervalIdRef.current);&lt;br /&gt;
       intervalIdRef.current = null;&lt;br /&gt;
    };&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;p&amp;gt;カウント: {count}&amp;lt;/p&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handleStart}&amp;gt;開始&amp;lt;/button&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={handleStop}&amp;gt;停止&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== WebSocketインスタンスの保持 ====&lt;br /&gt;
WebSocketのようなミュータブルなオブジェクトを保持する場合も、&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; が適切である。&amp;lt;br&amp;gt;&lt;br /&gt;
接続オブジェクト自体は画面に表示しないため、再レンダリングを発生させる必要がない。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useEffect, useRef, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export default function WebSocketExample() {&lt;br /&gt;
    const wsRef = useRef&amp;lt;WebSocket | null&amp;gt;(null);&lt;br /&gt;
    const [messages, setMessages] = useState&amp;lt;string[]&amp;gt;([]);&lt;br /&gt;
 &lt;br /&gt;
    useEffect(() =&amp;gt; {&lt;br /&gt;
       // WebSocket接続をrefで保持する&lt;br /&gt;
       wsRef.current = new WebSocket(&amp;#039;wss://example.com/ws&amp;#039;);&lt;br /&gt;
 &lt;br /&gt;
       wsRef.current.onmessage = (event) =&amp;gt; {&lt;br /&gt;
          setMessages(prev =&amp;gt; [...prev, event.data]);&lt;br /&gt;
       };&lt;br /&gt;
 &lt;br /&gt;
       return () =&amp;gt; {&lt;br /&gt;
          wsRef.current?.close();&lt;br /&gt;
       };&lt;br /&gt;
    }, []);&lt;br /&gt;
 &lt;br /&gt;
    const handleSend = (message: string) =&amp;gt; {&lt;br /&gt;
       wsRef.current?.send(message);&lt;br /&gt;
    };&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          {messages.map((msg, i) =&amp;gt; &amp;lt;p key={i}&amp;gt;{msg}&amp;lt;/p&amp;gt;)}&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; handleSend(&amp;#039;Hello&amp;#039;)}&amp;gt;送信&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== React 19でのrefの変更 ==&lt;br /&gt;
React 19では、&amp;lt;code&amp;gt;ref&amp;lt;/code&amp;gt; の扱いに重要な変更が加えられた。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;forwardRef()&amp;lt;/code&amp;gt; を使用せずに &amp;lt;code&amp;gt;ref&amp;lt;/code&amp;gt; を通常のpropとして渡せるようになり、ソースコードが大幅に簡潔になった。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== ref as prop ====&lt;br /&gt;
React 18以前では、子コンポーネントに &amp;lt;code&amp;gt;ref&amp;lt;/code&amp;gt; を渡すためには &amp;lt;code&amp;gt;forwardRef()&amp;lt;/code&amp;gt; でコンポーネントをラップする必要があった。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;React 19以降は、&amp;lt;code&amp;gt;ref&amp;lt;/code&amp;gt; を通常のpropとして受け取れるため、&amp;lt;code&amp;gt;forwardRef()&amp;lt;/code&amp;gt; が不要になった。&amp;lt;/u&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* React 18以前の実装&lt;br /&gt;
*: &amp;lt;code&amp;gt;forwardRef()&amp;lt;/code&amp;gt; を使用してrefを転送する方法である。&lt;br /&gt;
*: &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { forwardRef, useRef } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 interface MyInputProps {&lt;br /&gt;
    label: string;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // React 18以前 : forwardRefでラップが必要&lt;br /&gt;
 const MyInput = forwardRef&amp;lt;HTMLInputElement, MyInputProps&amp;gt;(&lt;br /&gt;
    function MyInput({ label }, ref) {&lt;br /&gt;
       return (&lt;br /&gt;
          &amp;lt;div&amp;gt;&lt;br /&gt;
             &amp;lt;label&amp;gt;{label}&amp;lt;/label&amp;gt;&lt;br /&gt;
             &amp;lt;input ref={ref} /&amp;gt;&lt;br /&gt;
          &amp;lt;/div&amp;gt;&lt;br /&gt;
       );&lt;br /&gt;
    }&lt;br /&gt;
 );&lt;br /&gt;
 &lt;br /&gt;
 export default function App() {&lt;br /&gt;
    const inputRef = useRef&amp;lt;HTMLInputElement&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    return &amp;lt;MyInput label=&amp;quot;名前&amp;quot; ref={inputRef} /&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*: &amp;lt;br&amp;gt;&lt;br /&gt;
* React 19以降の実装&lt;br /&gt;
*: &amp;lt;code&amp;gt;ref&amp;lt;/code&amp;gt; を通常のpropとして受け取る方法である。&lt;br /&gt;
*: &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useRef } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 interface MyInputProps {&lt;br /&gt;
    label: string;&lt;br /&gt;
    ref?: React.Ref&amp;lt;HTMLInputElement&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // React 19以降 : forwardRefは不要、refを通常のpropとして受け取る&lt;br /&gt;
 function MyInput({ label, ref }: MyInputProps) {&lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;label&amp;gt;{label}&amp;lt;/label&amp;gt;&lt;br /&gt;
          &amp;lt;input ref={ref} /&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 export default function App() {&lt;br /&gt;
    const inputRef = useRef&amp;lt;HTMLInputElement&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    return &amp;lt;MyInput label=&amp;quot;名前&amp;quot; ref={inputRef} /&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== useImperativeHandle ==&lt;br /&gt;
&amp;lt;code&amp;gt;useImperativeHandle&amp;lt;/code&amp;gt; は、親コンポーネントに公開するメソッドやプロパティを制御するHookである。&amp;lt;br&amp;gt;&lt;br /&gt;
子コンポーネントの実装の詳細を隠蔽しつつ、親が必要とするAPIのみを公開できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useRef, useImperativeHandle } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 interface InputHandle {&lt;br /&gt;
    focus: () =&amp;gt; void;&lt;br /&gt;
    clear: () =&amp;gt; void;&lt;br /&gt;
    getValue: () =&amp;gt; string;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 interface MyInputProps {&lt;br /&gt;
    ref?: React.Ref&amp;lt;InputHandle&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyInput({ ref }: MyInputProps) {&lt;br /&gt;
    const inputRef = useRef&amp;lt;HTMLInputElement&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    // 親に公開するAPIを定義する&lt;br /&gt;
    useImperativeHandle(ref, () =&amp;gt; ({&lt;br /&gt;
       focus() {&lt;br /&gt;
          inputRef.current?.focus();&lt;br /&gt;
       },&lt;br /&gt;
       clear() {&lt;br /&gt;
          if (inputRef.current) {&lt;br /&gt;
             inputRef.current.value = &amp;#039;&amp;#039;;&lt;br /&gt;
          }&lt;br /&gt;
       },&lt;br /&gt;
       getValue() {&lt;br /&gt;
          return inputRef.current?.value ?? &amp;#039;&amp;#039;;&lt;br /&gt;
       },&lt;br /&gt;
    }), []);  // 第3引数は依存配列&lt;br /&gt;
 &lt;br /&gt;
    return &amp;lt;input ref={inputRef} /&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 export default function App() {&lt;br /&gt;
    const inputHandle = useRef&amp;lt;InputHandle&amp;gt;(null);&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;MyInput ref={inputHandle} /&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; inputHandle.current?.focus()}&amp;gt;フォーカス&amp;lt;/button&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; inputHandle.current?.clear()}&amp;gt;クリア&amp;lt;/button&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; console.log(inputHandle.current?.getValue())}&amp;gt;値を取得&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== コールバックref ==&lt;br /&gt;
&amp;lt;code&amp;gt;ref&amp;lt;/code&amp;gt; 属性には、RefObjectだけでなくコールバック関数を渡すこともできる。&amp;lt;br&amp;gt;&lt;br /&gt;
コールバックrefは、要素がマウントされたときにDOM要素が引数として渡され、アンマウントされた時に &amp;lt;u&amp;gt;null&amp;lt;/u&amp;gt; が渡される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useCallback, useRef } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export default function CallbackRefExample() {&lt;br /&gt;
    // useCallbackでラップして不要な再呼び出しを防止する&lt;br /&gt;
    const inputCallbackRef = useCallback((node: HTMLInputElement | null) =&amp;gt; {&lt;br /&gt;
       if (node !== null) {&lt;br /&gt;
          // マウント時 : DOM要素が渡される&lt;br /&gt;
          node.focus();&lt;br /&gt;
          console.log(&amp;#039;マウント:&amp;#039;, node);&lt;br /&gt;
       }&lt;br /&gt;
       else {&lt;br /&gt;
          // アンマウント時 : nullが渡される&lt;br /&gt;
          console.log(&amp;#039;アンマウント&amp;#039;);&lt;br /&gt;
       }&lt;br /&gt;
    }, []);  // 依存配列が空のため、関数は一度だけ生成される&lt;br /&gt;
 &lt;br /&gt;
    return &amp;lt;input ref={inputCallbackRef} placeholder=&amp;quot;マウント時に自動フォーカス&amp;quot; /&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;コールバックrefは、要素のマウント・アンマウントのタイミングで処理を行う場合に特に有効である。&amp;lt;/u&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;&amp;lt;code&amp;gt;useCallback&amp;lt;/code&amp;gt; でラップしない場合、親コンポーネントが再レンダリングされるたびにコールバック関数が再生成され、不要な再呼び出しが発生するため注意が必要である。&amp;lt;/u&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== よくある間違い ==&lt;br /&gt;
&amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; の使用にあたって、よくある間違いと正しい対処法を以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== レンダリング中のref読み書き ====&lt;br /&gt;
&amp;lt;u&amp;gt;render関数本体でのレンダリング中に &amp;lt;code&amp;gt;ref.current&amp;lt;/code&amp;gt; を読み書きしてはいけない。&amp;lt;/u&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
初期化処理等を除いて、&amp;lt;code&amp;gt;ref.current&amp;lt;/code&amp;gt; へのアクセスはイベントハンドラや &amp;lt;code&amp;gt;useEffect&amp;lt;/code&amp;gt; 内で行う。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useEffect, useRef } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export default function WrongUsageExample() {&lt;br /&gt;
    const ref = useRef(0);&lt;br /&gt;
 &lt;br /&gt;
    // 正しい : useEffect内でrefを更新する&lt;br /&gt;
    useEffect(() =&amp;gt; {&lt;br /&gt;
       ref.current += 1;&lt;br /&gt;
       console.log(&amp;#039;レンダリング回数:&amp;#039;, ref.current);&lt;br /&gt;
    });&lt;br /&gt;
 &lt;br /&gt;
    // 誤り : レンダリング中 (render関数本体) でrefを書き換えている&lt;br /&gt;
    // ref.current += 1;  // Reactの描画処理と競合するため禁止&lt;br /&gt;
 &lt;br /&gt;
    return &amp;lt;div&amp;gt;コンポーネント&amp;lt;/div&amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== レンダリング用データへのref使用 ====&lt;br /&gt;
&amp;lt;u&amp;gt;画面に表示する値を &amp;lt;code&amp;gt;useRef&amp;lt;/code&amp;gt; で管理してはいけない。&amp;lt;/u&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ref.current&amp;lt;/code&amp;gt; の変更は再レンダリングを発生させないため、画面に反映されない。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;UIに表示する値は &amp;lt;code&amp;gt;useState&amp;lt;/code&amp;gt; で管理する。&amp;lt;/u&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { useRef, useState } from &amp;#039;react&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 export default function DataManagementExample() {&lt;br /&gt;
    // 正しい : 画面に表示する値はuseStateで管理する&lt;br /&gt;
    const [count, setCount] = useState(0);&lt;br /&gt;
 &lt;br /&gt;
    // 正しい : 画面に表示しない値はuseRefで管理する&lt;br /&gt;
    const renderCountRef = useRef(0);&lt;br /&gt;
    renderCountRef.current += 1;&lt;br /&gt;
 &lt;br /&gt;
    // 誤り : 画面に表示する値をrefで管理している&lt;br /&gt;
    // const countRef = useRef(0);&lt;br /&gt;
    // countRef.current += 1;  // 画面が更新されない&lt;br /&gt;
 &lt;br /&gt;
    return (&lt;br /&gt;
       &amp;lt;div&amp;gt;&lt;br /&gt;
          &amp;lt;p&amp;gt;カウント (画面に反映される): {count}&amp;lt;/p&amp;gt;&lt;br /&gt;
          &amp;lt;p&amp;gt;レンダリング回数 (ログ用): {renderCountRef.current}&amp;lt;/p&amp;gt;&lt;br /&gt;
          &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;増加&amp;lt;/button&amp;gt;&lt;br /&gt;
       &amp;lt;/div&amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 関連情報 ==&lt;br /&gt;
* [[Reactの基礎 - Hooksの基礎]]&lt;br /&gt;
* [[Reactの基礎 - useState]]&lt;br /&gt;
* [[Reactの基礎 - useEffect]]&lt;br /&gt;
* [[Reactの基礎 - カスタムHook]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{#seo:&lt;br /&gt;
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki&lt;br /&gt;
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板,React,JavaScript,TypeScript,TSX,useRef,useState,useEffect,Hook,DOM,forwardRef,useImperativeHandle,RefObject,MutableRefObject,コールバックref&lt;br /&gt;
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux&lt;br /&gt;
|image=/resources/assets/MochiuLogo_Single_Blue.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
__FORCETOC__&lt;br /&gt;
[[カテゴリ:Rust]][[カテゴリ:Web]]&lt;/div&gt;</summary>
		<author><name>Wiki</name></author>
	</entry>
</feed>