antonkornilov-ua
antonkornilov-ua

Reputation: 133

How to make animations works with IntersectionObserver in React app with Tailwind

I'm stuck. So what do I want from my app:

  1. to animate sections with left fading and opacity (0 to 1) when I scroll down or up.
  2. reuse this component later with different separate components.

What I have now:

  1. Js function that perfectly works with simple HTML and CSS.
  2. nothing from my 'want list'

Please help! My code is next:

import React from 'react';

const TestAnimation = () => {
const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
        if (entry.isIntersecting) {
            entry.target.classList.add('.opacity-100');
        } else {
            entry.target.classList.remove('.opacity-100');
        }
    });
});

const hiddenElements = document.querySelectorAll('.opacity-0');
hiddenElements.forEach((el) => {
    observer.observe(el);
});

    

    return (
        <div className='m-0 bg-slate-900 p-0 text-white'>
            <section className='grid min-h-screen place-items-center content-center opacity-0'>
                <h1>Test</h1>
            </section>
            <section className='grid min-h-screen place-items-center content-center opacity-0'>
                <h2>This is first page</h2>
                <p>
                    Lorem ipsum dolor, sit amet consectetur adipisicing elit. Autem modi voluptatem est iste a commodi
                    nesciunt saepe quisquam id dignissimos odit, repellat asperiores laboriosam quibusdam expedita
                    itaque blanditiis eos pariatur.
                </p>
            </section>
            <section className='grid min-h-screen place-items-center content-center opacity-0'>
                <h2>This is third page</h2>
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consectetur veniam sint illo quas beatae,
                    eum omnis, deleniti error, eveniet praesentium fugiat quia quod? Maxime, placeat reiciendis ab
                    debitis exercitationem nemo. Laborum perspiciatis eum architecto laboriosam, necessitatibus
                    voluptatibus cupiditate accusantium corrupti placeat mollitia omnis tenetur! Incidunt fugiat
                    possimus quod, quidem itaque ducimus, perspiciatis eligendi, commodi voluptate cupiditate nihil
                    corrupti soluta maxime.
                </p>
            </section>
            <section className='grid min-h-screen place-items-center content-center opacity-0'>
                <h2>this is Fourth page</h2>
                <p className='text-center'>
                    Lorem ipsum dolor sit amet consectetur adipisicing elit. Quos similique harum, officiis facere odit
                    adipisci maxime obcaecati placeat, quibusdam totam magni eaque? Dicta id commodi saepe dignissimos
                    quam unde eaque.
                </p>
            </section>
        </div>
    );
};

export default TestAnimation;

Upvotes: 1

Views: 732

Answers (1)

Hasan Aga
Hasan Aga

Reputation: 774

You should move the initiation of the intersection observer into a useEffect hook.

Here is an example of an Observer component I've used in the past:

export default function Observer({ children, sectionRef, callback }) {
  function onObserver(entries) {
    const entry = entries[0];
    console.log(entry);
    if (entry.isIntersecting) {
      callback(sectionRef.current.id);
      console.log("element in:", entry.target.id);
    } else {
      console.log("element left:", entry.target.id);
    }
  }

  useEffect(() => {
    const refCopy = sectionRef;

    let options = {
      root: null,
      rootMargin: "0% 0% -5% 0%",
      threshold: [0.5],
    };

    let observer = new IntersectionObserver(onObserver, options);

    if (refCopy.current) {
      observer.observe(refCopy.current);
    }
    return () => {
      if (refCopy.current) {
        observer.unobserve(refCopy.current);
      }
    };
  }, [sectionRef]);

  return <div id="observation">{children}</div>;
}

And here is how to use it:

export default function Education({ children, handleInView }) {
  const sectionRef = useRef(null);

  return (
    <Observer sectionRef={sectionRef} callback={handleInView}>
      <section
        ref={sectionRef}
        id="education"
        className="education"
        data-scroll-section
        data-scroll
        data-scroll-class="purpleColor"
      >
        <Pencils />
        <div className="details">
          <div className="side-by-side">
            <div className="title" data-scroll data-scroll-speed={2}>
              <span>Fullstack</span>
              <span> Software </span>
              <span>Engineer</span>
            </div>
            
          </div>
        </div>
      </section>
    </Observer>
  );
}

Upvotes: 2

Related Questions