ReactではDOMにアクセスする際にuseRefを使います。
あまり、積極的に使わない方が良さそうですが、使う機会があってあまり理解できていなかったので調べてみました。
useRefでDOMの横幅を知りたいときに、TypeScriptでは以下のように書いていました。
const SampleComponent = () => {
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
console.log(ref.current?.offsetWidth);
}, []);
return (
<div ref={ref}>
~~
</div>
);
}
恥ずかしながら、useRef(null)とかref.current?.offsetWidthってなんだっけと...
とりあえず、改めてrefの理解から。
useRef
は、.current
プロパティが渡された引数 (initialValue
) に初期化されているミュータブルな ref オブジェクトを返します。返されるオブジェクトはコンポーネントの存在期間全体にわたって存在し続けます。
まず、ref.currentでrefの現在の値が取得できるとのこと。
それはそうなんだけど、useRef<HTMLDivElement>
とHTMLDivElementの型を設定していて、なぜnullを引数に取るのかとか、ref.currentがnullになることがあるのか少し疑問に思っていました。
このIssueをみると、divに設定されるまではrenderされるまでnullが入るとのこと。レンダリングされるまでは何もないのでなんとなく納得。
次にoffsetWidthってなんだっけと。HTMLElementのプロパティらしい。
HTMLDivElementはHTMLElementを継承しているのでoffsetWidthを使えるみたいです。
https://developer.mozilla.org/ja/docs/Web/API/HTMLElement
なので、offsetWidth以外でもHTMLElementのプロパティやイベントを使えるはずです。
widthがなくて、offsetWidthなんだという点も疑問に思っていました。
ドキュメントや記事みてみると、なんとなく理由の想像ができました。
https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/offsetWidth
https://stackoverflow.com/questions/8133146/difference-between-style-width-and-offsetwidth-in-html
おそらくマージンや擬似要素の幅を含まないという理由か、もしくはstyleのwidthと混同させないためという理由な気がします。