Home > database >  How to fix type error with refs in a react hook?
How to fix type error with refs in a react hook?

Time:12-11

I have a useFadein hook

import { useRef, useEffect } from 'react';

export const useFadeIn = (delay = 0) => {
  const elementRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (!elementRef.current) return
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setTimeout(() => {
            if (!elementRef.current) return
            elementRef.current.classList.add('fade-in');
          }, delay);
        } else {
          if (!elementRef.current) return
          elementRef.current.classList.remove('fade-in');
        }
      },
      { rootMargin: '0px 0px -50% 0px' }
    );
    observer.observe(elementRef.current);
  }, [delay]);

  return { ref: elementRef };
};

I use the hook in my component

"use client"
import styles from "@components/Intro/Intro.module.scss"
import { useFadeIn } from "@hooks/useFadeIn"


const Intro = () => {
  const fadeInTitle = useFadeIn(200);
  const fadeInIntro = useFadeIn(400);
  const fadeInSocial = useFadeIn(600);

  return (
    <section className={styles.wrapper} >
      <h2 {...fadeInTitle}>Test</h2>
      <p {...fadeInIntro}>Test</p>
      <ul {...fadeInSocial} className={styles.socialLinks}>
        <li>
          <a href="#" target="_blank">Test</a>
        </li>
      </ul>
    </section>
  )
}

export { Intro }

But I get the following type errorenter image description here

If I replace HTMLElement with HTMLHeadingElement

const elementRef = useRef<HTMLHeadingElement>(null);

then a similar error with HTMLUListElement shows. If I use

const elementRef = useRef<HTMLHeadingElement | HTMLUListElement>(null);

Then both type errors show.

How can I solve the type error?

CodePudding user response:

You need to retype your custom hook with generic type.

Working example in codesanbox example

export const useFadeI = <T extends HTMLElement>(delay = 0) => {
  const ref = useRef<T | null>(null);

  useEffect(() => {
    const node = ref.current;
    if (!node) return;

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setTimeout(() => {
            node.classList.add("fade-in");
          }, delay);
        } else {
          node.classList.remove("fade-in");
        }
      },
      { rootMargin: "0px 0px -50% 0px" }
    );
    observer.observe(node);
  }, [delay]);

  return { ref };
};
  • Related