Jump to content
Search Community

timeline stagger in .map() (React)

javierGnz test
Moderator Tag

Recommended Posts

Hi all !

 

So i want to create a timeline of the <Item /> elements when i click the "on button", the problem is the animation plays all in one time, the stagger doesn't work.

 

I don't want to create a parent element that wrap the <Item /> elements and use "boxRef.current.children" because the idea is use in another part the <Item /> and have the same animation

 

import React, { useRef, useEffect, useState } from "react";
import gsap from "gsap";

const settings = [1, 2, 3, 4, 5, 6];

const Item = ({ item }) => {
  const tl = gsap.timeline();

  useEffect(() => {
    tl.from([boxRef.current], 1, { y: 100, opacity: 0, stagger: 1, delay: 1 });
  }, []);

  const boxRef = useRef(null);

  return (
    <div
      ref={boxRef}
      style={{
        width: "160px",
        height: "160px",
        background: "salmon",
        borderRadius: "4px"
      }}
    >
      {item}
    </div>
  );
};

export default function AnimatedBox() {
  const [sw, setSw] = useState(false);

  return (
    <div>
      <h4>turn on the sw</h4>
      <button onClick={() => setSw(!sw)}>on</button>
      {sw && (
        <>
          {settings.map((item) => {
            return <Item key={item} item={item} />;
          })}
        </>
      )}
    </div>
  );
}

 

Link to comment
Share on other sites

28 minutes ago, javierGnz said:

I don't want to create a parent element that wrap

 

You already have a parent element i.e. your AnimatedBox, and the best option is do animations inside there. You can also pass down the index and create your delay. Or even pass down a timeline.

 

BTW, it's not a good idea to create a timeline inside the function like that.

 

// bad
const Item = ({ item }) => {
  const tl = gsap.timeline(); 

  useEffect(() => {
    tl.from([boxRef.current], 1, { y: 100, opacity: 0, stagger: 1, delay: 1 });
  }, []);
};

// ok
const Item = ({ item }) => {
  const tl = useRef(); 

  useEffect(() => {
    tl.current = gsap.timeline()
      .from([boxRef.current], 1, { y: 100, opacity: 0, stagger: 1, delay: 1 });
    
    return () => tl.current.kill();
  }, []);
};

// ok
const Item = ({ item }) => {
  
  useEffect(() => {
    const tl = gsap.timeline()
      .from([boxRef.current], 1, { y: 100, opacity: 0, stagger: 1, delay: 1 });
    
    return () => tl.kill();
  }, []);
};

 

 

 

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...