34
14

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 3 years have passed since last update.

Reactで要素の高さを取得するためDOMを扱う2つのやり方【useRef】

Last updated at Posted at 2020-09-05

Reactで要素を取得する2つのやり方を紹介する。

  1. document.getElementById()などを用いたやり方。
  2. useRefを用いたやり方

document.getElementById()などを用いたやり方

getRect.getBoundingClientRect()を使って取得します。

sample.js
import React from "react";
import "./styles.css";

const getRectFunc = () => {
  const getRect = document.getElementById("getRectBtn");
  console.log(JSON.stringify(getRect.getBoundingClientRect()));
};

const App = () => { 
  return (
    <div>
      <button id="getRectBtn" onClick={getRectFunc}>
        button
      </button>
    </div>
  );
};

export default App;


codesandbox: https://codesandbox.io/s/nostalgic-architecture-c1tq8?fontsize=14&hidenavigation=1&theme=dark

例としてボタンをクリックするとDOMを取得してgetRectFunc()関数が走ってDOMを取得するサンプルです。

sample.js
const getRectFunc = () => {
  const getRect = document.getElementById("getRectBtn");
  console.log(JSON.stringify(getRect.getBoundingClientRect()));
};

結果として

{"x":8,"y":11,"width":53.0625,"height":21,"top":11,"right":61.0625,"bottom":32,"left":8} 

が帰ってくる。

useRefとは

Reactの 16.8v から対応した React Hooks の一機能。
useRefはReactのDOM要素へアクセスできDOMの状態を取得できる。

HooksのReactライフサイクル上でいうとLayoutフェーズもしくはCommitフェーズの副作用となるため更新する場合はuseEffect(useLayoutEffect)を一緒に用いて更新することが多い。

したがって、renderingフェーズでは値が前回の状態のままとなっている。

sample.js
import React, { useRef, useEffect } from "react";
import useRefSample from "./useRefSample";

const App = () => {
  const elm = useRef(null);
  const SampleComponent = useRefSample;

  useEffect(() => {
    console.log(elm.current);
    console.log(JSON.stringify(elm.current.getBoundingClientRect()));
  }, []);

  return (
    <div ref={elm}>
      <SampleComponent />
    </div>
  );
};

export default App;

codesandbox: https://codesandbox.io/s/shy-framework-4y937?fontsize=14&hidenavigation=1&theme=dark

useRef(null)と初期値を入れている

sample.js
const elm = useRef(null);

DOMに ref={elm} と直接、埋め込むことでDOMを取得できる。

sample.js
    <div ref={elm}>
      <SampleComponent />
    </div>

console.log(elm.current)の結果は以下の通り。子のDOMも一緒に取得できている。

current とは useRef でデフォルトで用意されているプロパティ。
useRef で任意の値を更新するときは直接 elm へ代入せずに elm.current へ代入することが必要となる。

sample.js
<div>
  <div id="sampleDom">Hello,サンプルのDOMです</div>
</div>

console.log(JSON.stringify(elm.current.getBoundingClientRect()));の結果は以下の通り。

sample.js
{"x":8,"y":8,"width":538,"height":24,"top":8,"right":546,"bottom":32,"left":8} 

DOMに ref={hoge} を埋め込まなくても使えるuseRef

蛇足だが先ほどの例では親要素にref属性をつけて子要素ごとDOMを取得することができた。

ただし、useRef自体に数字の状態を入れておいて常に最新のrenderingフェーズよりも1つ前の状態を維持するような使い方もできる。

あえてuseRefを使う意味はあるのか

Reactの原則である単一方向のデータフローを考えるとuseRefの方が適していると言える。

getElementByIdやquerySelectorはイミュータブルで、意図しないDOMを取得する可能性があり、データフローを無視してエレメントを取得してしまう。

34
14
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
34
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?