網站搜尋

reactjs - 為什麼 `ref.current.clientHeight` 總是可能為 null?


我正在嘗試找出該元件的高度(以像素為單位),因為它的高度將在 CSS 中設置為 100%

import React, { useState, useLayoutEffect, useRef } from "react";

function Scale() {
  const [height, setHeight] = useState(0);
  const ref = useRef(null);
  useLayoutEffect(() => {
    if (ref && ref.current && ref.current.clientHeight) {
//                              ^ error: Object is possibly 'null'
      const height = ref.current.clientHeight;
      setHeight(height);
    }
  });
  return (
    <div className="scale" ref={ref}>
      {height}
    </div>
  );
}

export { Scale };

答案#1

ref 永遠不會是 null,因為它是 const,一開始就不是 null,所以 if (ref) 是沒用的。

useRef<T>(x: T | null) 的類型是 MutableRefObject<T>。在這裡,T 是 null,所以 ref.current 的類型是 null。

要解決這個問題,請指定設定後它的類型:

  const ref = useRef(null as null | HTMLDivElement);
  // Or manually specify the type parameter
  const ref = useRef<HTMLDivElement>(null)
  useLayoutEffect(() => {
    if (ref.current && ref.current.clientHeight) {
      const height = ref.current.clientHeight;
      setHeight(height);
    }
  });

答案#2

if (ref && ref.current && ref.current.clientHeight) {
   //                        ^ error: Object is possibly 'null'
   const height = ref.current.clientHeight;
   setHeight(height);
}

這個語句應該可行,但 TypeScript 經常不會如我們預期地進行推斷。

所以,最佳解決方案(不只是一些臨時的變通方法)是使用 Babel 的 Optional Chaining 外掛。

將它加入你的 .babelrc.js,你就可以用它取代那個語句

if (ref?.current?.clientHeight) {
   const height = ref.current.clientHeight;
   setHeight(height);
}

這其實是 TypeScript 3.7 原生的功能,所以它運作得非常順利。