React HookのuseRefを使うことで、どのようなことができるの?
useRefを使うことで主にDOMにアクセスして参照することができるよ!
Hooksとは?
Hook(フック)とはReact 16.8のバージョンで新しくで追加された機能です。
Hookは関数コンポーネントで使うことができる機能で、クラスを書かなくてもstateなどの機能を使えるようになります。
useEffectはHookの1つの機能です。
useRefとは?
「useRef
」はDOMを参照して要素にアクセスするためのフックです。
また、useRefはコンポーネント内での値を保持することもできます。
useRefはレンダリングを起こさず値を保持することが特徴で、useStateなどレンダリングさせたくないときに使います。
useRefの使い方
まずはuseRefの機能をインポートします。
インポートしなくても使えますが、 今回はインポートをして使っていきます。
import React, { useRef } from 'react';
インポートができたらuseRefを使うことができるようになります。
useRefの定義を変数にセットするのが基本の記述になります。
const 変数 = useRef(初期値);
useRefを使った構文の例です。
const number = useRef(10);
console.log(number.current); // 10
useRefは.current
プロパティに値を保持します。
そのためuseRefの値を取得したり更新したりするときは.current
プロパティ経由で行います。
useRefは.current
プロパティに書き換え可能な値を保持することができる「箱」のようなイメージです。
DOMを参照するとき
useRefはDOMにアクセスする手段としても利用されます。
ReactではDOMノードに変更がある度に.current
プロパティをその DOMノードに設定していきます。
DOMを使った例を使って解説をしていきます。
最初にuseRefを初期値をnull
で定義しておきます。
DOMを扱う際は基本的に初期値はnull
でOKです。
const inputTextElement = useRef(null);
次にDOMアクセスしたい要素のref属性にuseRefを定義しているinputTextElement
変数を設定します。
<input type="text" ref={inputTextElement} />
これでinputTextElement変数を使ってinput要素にアクセスできるようになりました。
console.log
でinputTextElement.current
をしてみると以下のようにinput要素を参照することができます。
console.log(inputTextElement.current); // <input type="text" />
input要素にフォーカスをさせる
useRefを使うことでDOMにアクセスができるため、input要素にフォーカスをさせることができます。
import React, { useRef } from 'react';
export const Count = () => {
const inputTextElement = useRef(null);
const focusInputText = () => {
inputTextElement.current.focus(); // フォーカスをする
};
return (
<div>
<p>カウント: {count}</p>
<input ref={inputTextElement} type="text" />
<button onClick={focusInputText}>テキスト入力欄にフォーカスする</button>
</div>
);
}
「テキスト入力欄にフォーカスする」ボタンをクリックすることで、テキスト入力欄にフォーカスされます。
focusInputText
関数ではinputTextElement.current
でフォーカスする対象のinput要素を参照し、その要素に対してfocus()
関数を実行しフォーカス処理をしています。
JavaScriptでdocument.getElementById('対象のid').focus()
のようにしてフォーカスをさせるのと同じ処理になります。
CSSのスタイルを変更する
DOMにアクセスできるため、対象の要素をCSSでスタイルを変更できます。
import React, { useRef } from 'react';
export const Count = () => {
const textElement = useRef(null);
const changeRedColor = () => {
textElement.current.style.color = 'red'; // フォーカスをする
};
return (
<div>
<p>カウント: {count}</p>
<p ref={textElement} />赤色に変わります</p>
<button onClick={changeRedColor}>赤色に変える</button>
</div>
);
}
この例では「赤色に変える」ボタンをクリックすると赤色に変えるCSSを適用し、色を変更させています。
useRefに値を保持するとき
useRefはレンダリングを起こさず値を保持することが特徴と前述しましたが、この特徴をもう少し深堀りしたいと思います。
useRefはとても分かりやすい設計で、{current: 初期値}
というRefオブジェクトを生成し、その値を保持するものです。
値の取り出しや変更は.current
を使って行います。
// useRefの作成
const ref = useRef(0)
// 設定した値を取り出す
const value = ref.current;
// 値を変更する
const ref.current = 100;
useRefでは.current
の値を変更させているだけなので再レンダリングが起こりません。
これがレンダリングを起こさない特徴でその理由です。
1回だけ実行したい処理があるとき
レンダリングを起こさない特徴を利用して、1回だけ実行したい処理があったときはuseRefを使います。
例えば決定ボタンを複数回クリックされるのを防ぎたいときにuseRefを使います。
const OnlyButton = () => {
const processing = useRef(false);
const clickButton = (e) => {
e.preventDefault();
e.stopPropagation();
processing.current && return; // 処理中(true)なら抜ける
processing.current = true; // 処理中フラグを立てる
// 1回だけ実行したい処理
// 再度実行させたいときは処理中フラグを下げる
process.current = false;
}
return (
<div>
<button onClick={clickButton}>クリック</button>
</div>
)
}
このように処理中のフラグを使って1回だけ処理をしたいときなどに使うことができます。
この使い方はレンダリングをしてしまうuseStateではできないので、この特徴を覚えておきましょう。
まとめ
- useRefはDOMを参照して要素にアクセスするためのフック
- レンダリングを起こさず値を保持することが特徴
useRefの使い方と特徴について分かったかな?
useRefの特徴分かったよ!そして覚えた!