簡體   English   中英

React ForwardRef:“ForwardedRef”類型上不存在屬性“current”<htmlelement> '</htmlelement>

[英]React ForwardRef: Property 'current' does not exist on type 'ForwardedRef<HTMLElement>'

我正在嘗試創建一個跟蹤垂直滾動的組件。 問題是——實際的滾動容器不容易預測(在這種特定情況下,它既不是windowdocument也不是body ——它是div#__next ,由於 CSS 溢出規則)。

我想保持組件的靈活性和獨立性。 所以我創建了一個帶有 DOM 選擇器的ref作為參數。 我知道這遠非慣用語(至少可以說),但令人驚訝的是,它似乎在起作用:

// Parent component
import { useRef } from "react"

const Article = (props) => {
  const scrollContainerRef = useRef<HTMLElement | null>(
    document.querySelector("#__next") // <-- the scroll container reference
  )

  return (
    <SomeContent>
      <ScrollToTop treshold={640} ref={scrollContainerRef} />
    </SomeContent>
)
// ScrollToTop
const ScrollToTop = forwardRef(
  ({ treshold }, ref) => {
    const [visible, setVisible] = useState(false)

    useEffect(() => {

      if (ref?.current) {
        ref.current.addEventListener("scroll", throttle(toggleVisible, 300))
        return () => {
          ref.current.removeEventListener("scroll", throttle(toggleVisible, 300))
        }
      }
    }, [])
// …

所以有什么問題? 當前一個是 Typescript 我花了幾個小時試圖讓類型正確,但無濟於事。 父組件沒有紅色波浪線(除非我通過globalThis ,這似乎至少在 CodeSandbox 中有效),但是每當我訪問current屬性時ScrollToTop都會出現:

Property 'current' does not exist on type 'ForwardedRef<HTMLElement>'.

我試過使用React.MutableRefObject<HTMLElement | null /* or other T's */> React.MutableRefObject<HTMLElement | null /* or other T's */> ,無論是在父母身上還是在孩子身上,但它沒有幫助。

任何想法如何讓類型匹配? 或者這從一開始就是一個愚蠢的想法?

CodeSandbox 演示

Refs可能是具有.current屬性的對象,但它們也可能是函數。 因此,您不能假設轉發的 ref 具有.current屬性。

我認為在這里使用forwardRef是一個錯誤。 forwardRef的目的是允許父組件訪問子組件中的元素。 但是相反,父元素是找到元素的人,然后您將其傳遞給子元素以供其使用。 我會使用常規的 state 和道具:

const Article = (props) => {
  const [scrollContainer, setScrollContainer] = useState<HTMLElement | null>(() => {
    return document.querySelector("#__next");
  });

  return (
    <SomeContent>
      <ScrollToTop treshold={640} scrollContainer={scrollContainer} />
    </SomeContent>
)

interface ScrollToTopProps {
  treshold: number;
  scrollContainer: HTMLElement | null;
}

const ScrollToTop = ({ treshold, scrollContainer }: ScrollToTopProps) => {
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    if (scrollContainer) {
      const toggle = throttle(toggleVisible, 300);
      scrollContainer.addEventListener("scroll", toggle);
      return () => {
        scrollContainer.removeEventListener("scroll", toggle);
      }
    }
  }, [scrollContainer]);
  // ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM