How to use multiple 'useInView' hooks in the same react component?

10.3k views Asked by At

I'm working on a react project and trying to animate and show the divs once they're in the view. I'm using the useInView hook from 'react-intersection-observer' to determine if the div is in the view and then start the animation to make the div visible.

However, this doesn't work fine when I have two divs in the same component i.e, as soon as the first div is in the view - animate and show the first div, and when you scroll further as soon as the second div is in the view - animate and show the second div.

Any help would be appreciated.

Here's the code:

import { motion } from 'framer-motion';
import { useInView } from 'react-intersection-observer';

function Container(props) {

    const { ref, inView } = useInView({
        threshold: 1
    });

    const { ref1, inView1 } = useInView({
        threshold: 1
    });

    return (
        <div>
            <motion.div ref={ref}>
                <motion.h1 
                   initial={{  x: -700, opacity: 0 }} 
                   animate={ inView ? { x: 0,  opacity: 1 } : ''} 
                   transition={{ duration: .75 }} >
                     Sample Title 1
                </motion.h1>
                <motion.p 
                   initial={{  x: 400, opacity: 0 }} 
                   animate={ inView ? { x: 0,  opacity: 1 } : ''} 
                   transition={{ delay: 0.8, duration: 1, ease: "easeOut" }} >
                     Sample Description 1
                </motion.p>
            </motion.div>

            <motion.div ref={ref1}>
                <motion.h1 
                   initial={{ opacity: 0 }} 
                   animate={ inView1 ? { opacity: 1 } : ''} 
                   transition={{ duration: .75 }} >
                     Sample Title 2
                </motion.h1>
                <motion.p
                   initial={{  x: 400, opacity: 0 }} 
                   animate={ inView1 ? { x: 0,  opacity: 1 } : ''} 
                   transition={{ delay: 0.8, duration: 1, ease: "easeOut" }} >
                     Sample Description 2
                </motion.p>
            </motion.div>         
        </div>
    );
}

export default Container;



2

There are 2 answers

0
Gleb Shaltaev On BEST ANSWER

I guess you should correctly connect animation with intersection events

  1. Animation control: https://www.framer.com/api/motion/utilities/#animate
  2. InVew from 'react-intersection-observer' with
const from = useMotionValue(0);

useEffect(
  () => {
    if (inView) {
      const controls = animate(x, 100, {
        type: "spring",
        stiffness: 2000,
      })

      return controls.stop
    }
  },
  [inView]
}
0
tyro On

in their documentation it says you can use multiple variables with array destructuring and not object destructuring which you used in your own case.

So you should do this instead.

const [ref, inView ] = useInView()
const [ref2, inView2 ] = useInView()