最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to type a ref parameter with Typescript - Stack Overflow

programmeradmin3浏览0评论

I am new to Typescript and I'm currently trying to migrate one of my React.js projects to Typescript. One of the things I stumble on are refs. I have written a hook that is using a ref as a paremeter. Basically it detects if there is a click outside of a div and fire a function that's passed as second parameter. Now I'm wondering how I can type that specific ref. I've tried different solutions such as React.RefObject<any> but don't think using any would be a good idea? What can I use instead? The value is either undefined or a div (Container ponent is styled ponent), see code:

Hook

// How to type `ref`?
export function useOnClickOutside(ref: React.RefObject<any>, handler: Function) {
  useEffect(
    () => {
      const listener = (event: MouseEvent | TouchEvent) => {
        // Do nothing if clicking ref's element or descendent elements
        if (!ref.current || ref.current.contains(event.target)) {
          return
        }

        handler(event)
      }

      // MouseEvent
      document.addEventListener('mousedown', listener)
      // TouchEvent
      document.addEventListener('touchstart', listener)

      return () => {
        document.removeEventListener('mousedown', listener)
        document.removeEventListener('touchstart', listener)
      }
    },
    // Add ref and handler to effect dependencies
    [ref, handler]
  )
}


Component

  const containerRef = React.useRef()
  useOnClickOutside(containerRef, () => setIsOpen(false))

  // Some code

  <Container ref={containerRef}>
    // Some code
  </Container

So basically: What should <any> be instead? Thanks in advance.

I am new to Typescript and I'm currently trying to migrate one of my React.js projects to Typescript. One of the things I stumble on are refs. I have written a hook that is using a ref as a paremeter. Basically it detects if there is a click outside of a div and fire a function that's passed as second parameter. Now I'm wondering how I can type that specific ref. I've tried different solutions such as React.RefObject<any> but don't think using any would be a good idea? What can I use instead? The value is either undefined or a div (Container ponent is styled ponent), see code:

Hook

// How to type `ref`?
export function useOnClickOutside(ref: React.RefObject<any>, handler: Function) {
  useEffect(
    () => {
      const listener = (event: MouseEvent | TouchEvent) => {
        // Do nothing if clicking ref's element or descendent elements
        if (!ref.current || ref.current.contains(event.target)) {
          return
        }

        handler(event)
      }

      // MouseEvent
      document.addEventListener('mousedown', listener)
      // TouchEvent
      document.addEventListener('touchstart', listener)

      return () => {
        document.removeEventListener('mousedown', listener)
        document.removeEventListener('touchstart', listener)
      }
    },
    // Add ref and handler to effect dependencies
    [ref, handler]
  )
}


Component

  const containerRef = React.useRef()
  useOnClickOutside(containerRef, () => setIsOpen(false))

  // Some code

  <Container ref={containerRef}>
    // Some code
  </Container

So basically: What should <any> be instead? Thanks in advance.

Share Improve this question asked Sep 30, 2020 at 16:47 GiesburtsGiesburts 7,65816 gold badges52 silver badges92 bronze badges 3
  • You can use <HTMLDivElement> as mentioned in medium./@martin_hotell/… – Sujit Kumar Singh Commented Sep 30, 2020 at 17:01
  • Is it optional or you will get always? – Suleman Ahmad Commented Sep 30, 2020 at 17:07
  • ref.current.contains(event.target) this means your ref should be typed to have a contains method that takes a HTMLElement as input, I.E. the ref is to a HTMLElement. – Tadhg McDonald-Jensen Commented Sep 30, 2020 at 17:35
Add a ment  | 

1 Answer 1

Reset to default 9

the only part that is related to the type of the ref is this line:

    if (!ref.current || ref.current.contains(event.target)) {

This means the ref is something that has a contains method that takes as input a EventTarget | null object, so the minimum you would need to make it work is this:

interface ValidRefTarget {
  contains(target: EventTarget | null): any;
}

export function useOnClickOutside(ref: React.RefObject<ValidRefTarget>, handler: (event: MouseEvent | TouchEvent)=>void ) {

However since this method is provided by the HTMLElement object you probably want to just use that instead:

export function useOnClickOutside(ref: React.RefObject<HTMLElement>, handler: (event: MouseEvent | TouchEvent)=>void ) {
发布评论

评论列表(0)

  1. 暂无评论