useRefとは?
useRef
とはDOM要素の参照を保存したり、レンダリング間で変更されない値を保持するために利用されます。
ユースケース
- DOM要素の参照を保持
- レンダリング間で変更されない値を保持
DOM要素の参照を保持する
1. useRef
を利用して変数を作成する
-
useRef
を実行し、戻り値のRefObject
を変数に取る。const inputRef = useRef<HTMLInputElement>(null);
-
引数: 初期値(ここでは
null
) -
ジェネリック: 保存するReact要素の型(ここでは
HTMLInputElement
)
-
引数: 初期値(ここでは
2. ref
プロパティを使用してDOM要素にRefObject
を指定する
-
input
要素にref
プロパティを使用し、RefObject
を指定する<input type="text" ref={inputRef} />
3. DOM要素にアクセスする
RefObject
に保存した値はcurrent
プロパティに保存されています。
const handleClick = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleClick}>フォーカス</button>
</div>
);
useRefの注意点
current
プロパティに参照が保存されるタイミングは、コンポーネントがマウントされたタイミングになります。
componentDidMount
引用元
そのため、コンポーネントマウント前にcurrent
プロパティにアクセスすると、null
が返されます。
const Sample: React.FC = () => {
const inputRef = useRef<HTMLInputElement>(null);
console.log(inputRef.current); // => null
return (
<>
<input type="text" ref={inputRef} />
</>
);
};
対処法として、以下2つの方法があります。
-
useEffect
を利用する -
ref
コールバックを利用する
useRef + useEffect
useEffect
はコンポーネントのマウント後に実行されるため、current
プロパティに値が格納された後に実行することができます。
const Sample: React.FC = () => {
const inputRef = useRef<HTMLInputElement>(null);
console.log(inputRef.current); // => null
useEffect(() => {
console.log(inputRef.current); // => <input type="text">
}, []);
return (
<>
<input type="text" ref={inputRef} />
</>
);
};
useRef + refコールバック
ref
属性にコールバック関数を渡す方法です。
関数はコンポーネントのマウント時と、アンマウント時に実行されます。
アンマウント時は、引数にnull
を与えて関数を呼び出します。
呼び出しは初回のみで良いため、useCallback
を使用して、メモ化しています。
const Sample: React.FC = () => {
const inputRef = useRef<HTMLInputElement>(null);
console.log(inputRef.current); // => null
const inputRefCallback = useCallback((input: HTMLInputElement | null) => {
if (input === null) return;
console.log(input); // => <input type="text">
}, []);
return (
<>
<input type="text" ref={inputRefCallback} />
</>
);
};
参考にさせていただいた記事
レンダリング間で変更されない値を保持する
1. useRefを利用して変数を作成する
-
useRef
を実行し、変数を作成const countRef = useRef(0);
2. 変数の値を更新する
-
current
プロパティを使用して、変数の値を更新const incrementCount = () => { countRef.current += 1; console.log(countRef.current); };
3. 変数の値を使用する
- 変数の値はコンポーネントが再レンダリングされても保持される
const MyComponent = () => {
const countRef = useRef(0);
const incrementCount = () => {
countRef.current += 1;
console.log(countRef.current);
};
return (
<div>
<p>レンダリング間で変更されない値: {countRef.current}</p>
<button onClick={incrementCount}>カウントアップ</button>
</div>
);
};
まとめ
-
useRef
は、DOM要素の参照を保持するために利用される - 上記とは別に、再レンダリングされても値がリセットされない変数を保持するためにも使用される
-
RefObject.current
で値を読み書きし、必要に応じてその値を利用する