90
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ちーずのフロントエンド道場Advent Calendar 2021

Day 4

【React】useRefの基本的な使い方・活用術・注意点

Last updated at Posted at 2021-12-04

おはこんばんちは、@ちーずです。
アドベントカレンダー4日目、本日のテーマはuseRefです!!

useRefとは

useRefとは、参照を保持するためのhookです。

// 変数名 = useRef(初期値)
const ref = useRef(initialValue)

useRefはとてもシンプルな設計で、
Refオブジェクト({current: initialValue}) を生成して、その値をメモ化しているだけです。

値の取り出し、変更は下記のように書きます。

// 設定した値を取り出す
const value = ref.current;

// 値を変更する
const ref.current = 2;

つまり、ref.currentの値を変更させているだけなので
再レンダリングが走らないです。

これが、useRefの最大の特徴です。

▼ 参考

useRefの活用術

DOMに対する参照

圧倒的にこの使われ方が多いuseRefですが、
HTML要素にrefという属性でuseRefの値を渡してあげることで参照できます。

// useRefの型
// interface MutableRefObject<T> {
//  current: T;
// }
// function useRef<T>(initialValue: T): MutableRefObject<T>;

export const InputComponent = () => {
  const inputElement = useRef<HTMLInputElement>(null)

  return <input ref={inputElement}/>
}

これだけで、
inputElement.current.focus()でフォーカスさせたり、
inputElement.current.offsetHeightで高さを取得したりすることができます。

値に対する参照

9割くらいDOMの参照として使われているイメージですが、値に対して使うケースもあります。

一回のみ実行したい

再レンダリングが発生しない点を利用して、
一回のみ実行したい処理があった時の制御でuseRefを使うことができます。

const once = useRef(true);

useEffect(() => {
 if (!once.current) return;
 // 実行したい処理
 once.current = false;
}, [])

useStateの前の値を保持する

公式ドキュメントにも記載がありますが、前の値を保持する時にuseRefを使います。

const [count, setCount] = useState(0);
 
const prevCountRef = useRef();
useEffect(() => {
  prevCountRef.current = count;
});

const prevCount = prevCountRef.current;

どのような仕組みで前の値が保持されているかは、下記の記事にてとてもわかりやすく説明されていたため、参考にしてください。

▼ 参考

useRefの注意点

useEffectの第二引数にいれても、変更を検知しない

今までの話を通して、「そりゃそうだろ!!」 と思うかもしれませんが

たとえ第二引数にref.currentを書いたとしても、
再レンダリングが起きないため、値が変更しても検知できません。


export const InputComponent = () => {
  const inputElement = useRef<HTMLInputElement>(null)

  useEffect(() => {
    if(inputElement.current) {
      // 実行したい処理   
    }
  }, [inputElement.current]);
  

  return <input ref={inputElement}/>
}

しかし、初期状態でマウントされておらず、nullになり続けてしまうケースもあるでしょう。
そのような時は、コールバックRefが使えるかもしれません。
(自分は使ったことがいまのところないです。)


以上、「useRefの基本的な使い方と活用術」でした!

90
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
90
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?