繁体   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