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 component is styled component), 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.
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 ) {
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With