Reactで要素を取得する2つのやり方を紹介する。
- document.getElementById()などを用いたやり方。
- useRefを用いたやり方
document.getElementById()などを用いたやり方
getRect.getBoundingClientRect()を使って取得します。
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を取得するサンプルです。
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フェーズでは値が前回の状態のままとなっている。
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)と初期値を入れている
const elm = useRef(null);
DOMに ref={elm} と直接、埋め込むことでDOMを取得できる。
<div ref={elm}>
<SampleComponent />
</div>
console.log(elm.current)の結果は以下の通り。子のDOMも一緒に取得できている。
current とは useRef でデフォルトで用意されているプロパティ。
useRef で任意の値を更新するときは直接 elm へ代入せずに elm.current へ代入することが必要となる。
<div>
<div id="sampleDom">Hello,サンプルのDOMです。</div>
</div>
console.log(JSON.stringify(elm.current.getBoundingClientRect()));の結果は以下の通り。
{"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を取得する可能性があり、データフローを無視してエレメントを取得してしまう。