skip to Main Content

I have Parent component where I define some refs. Then I create an object of all these refs. And then pass this object to ref of child component.

Parent component is just a page component, child components are sections on this page. And Inside child components I have button, by click on which I scroll to next section.


const Home: React.FC = () => {
  const effectiveCoursesRef = useRef(null);
  const reviewsRef = useRef(null);
  const howWorksRef = useRef(null);
  const scienceBehindRef = useRef(null);
  const FAQRef = useRef(null);

  const refObject = {
    effectiveCoursesRef,
    reviewsRef,
    howWorksRef,
    scienceBehindRef,
    FAQRef,
  };
  
  return (
    <MainLayout
    >
      <main>
        <EffectiveCourses ref={refObject} />
        <Reviews ref={refObject} />
        <HowSleepSchoolWork ref={refObject} />
        <ScienceBehind ref={refObject} />
        <FAQ ref={refObject} />
      </main>
    </MainLayout>
  );
};

export default Home;

In child component I’m getting refs in forwardRef


const ScienceBehind = forwardRef((_, ref: any) => (
  <section className={`${styles.section}`} ref={ref.scienceBehindRef}>
    <div className="container">
      <h2 className={styles.sectionTitle}>Science behind Sleep School</h2>
      <ArrowButton ref={ref.FAQRef} color="#082B4B" />
    </div>
  </section>
));

export default ScienceBehind;

This approach works fine, but I have typescript errors. Please help me to figure out how to type this code and solve errors. Or a better approach how to achieve the same.
Here is error from Parent component
And Here is error from child component

Any help appriciated!
Regards, Anna.

I have tried to type it, but I still have error.

enter image description here

2

Answers


  1. Chosen as BEST ANSWER

    I still not resolved problem with typings, but for now it seems not resolvable. Because React doeasn't expect we will pass multiple refs with forward ref I guess. If someone come up with a solution please reply.

    I implemented another approach. Maybe this will help for someone as well. The approach is passing normal ref and onClick to child component, inside onClick call goToSection function. In this approah I do not need to pass ref to child and I do not have typings problem.

    Here is Parent

    const Home: React.FC = () => {
      const effectiveCoursesRef = useRef(null);
      const reviewsRef = useRef(null);
      const howWorksRef = useRef(null);
      const scienceBehindRef = useRef(null);
      const FAQRef = useRef(null);
      const moreSleepHelpRef = useRef(null);
    
      const isTabletOrMobile = useMediaQuery({ query: `(max-width: 875px)` });
    
    
      return (
        <MainLayout
        >
          <main>
            <HowSleepSchoolWork
              ref={howWorksRef}
              onClick={() =>
                goToSection(document, scienceBehindRef, isTabletOrMobile)
              }
            />
            <ScienceBehind
              ref={scienceBehindRef}
              onClick={() => goToSection(document, FAQRef, isTabletOrMobile)}
            />
            <FAQ
              ref={FAQRef}
              onClick={() =>
                goToSection(document, moreSleepHelpRef, isTabletOrMobile)
              }
            />
          </main>
        </MainLayout>
      );
    };
    
    export default Home;

    Here is Child component

    const ScienceBehind = forwardRef(
      ({ onClick }: Props, ref: React.Ref<HTMLDivElement>) => (
        <section className={`${styles.section}`} ref={ref}>
          <div className="container">
            <div>
              <ArrowButton color="#082B4B" onClick={onClick} />
            </motion.div>
          </div>
        </section>
      ),
    );
    
    export default ScienceBehind;

    Here is goToSection function

    export const goToSection = (document, ref, isTabletOrMobile) => {
      if (document) {
        const header = document.querySelector(`header`);
        const headerHeight = header.offsetHeight;
        window.scrollTo({
          top: isTabletOrMobile
            ? ref.current.offsetTop
            : ref.current.offsetTop - headerHeight,
          behavior: `smooth`,
        });
      }
    };


  2. Sometime ago i was also facing somewhat similar issue as yours and this did the trick for me. Although I am not sure if this will work for you as well but you can try adding type when you define your ref.

    const scienceBehindRef = useRef<ScienceBehindRefType>(null);
    

    Edit 31-08-23

    Sorry about that, i tried to recreate your issue what is basicly happening is that when you wrap your ScienceBehind with forwardRef it expects a ref in the ref key

    And in your case you are passing a object containing the refs

    <ScienceBehind
      ref={refObject} // expects a ref
    />
    

    I would suggest you should do it like this if you want to pass multiple refs in a component

    <ScienceBehind
      ref={refObject.scienceBehindRef} // or just pass scienceBehindRef directly
      otherRefs={refObject}
    />
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search