Reputation: 623
I'm having some problems getting the framer motions "staggerChildren" transition to work on a simple list of items. It basically allows animations of child components to be staggered.
I got my animation properties set up like this, for the parent container and the children:
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: {
staggerChildren: 0.5
}
}
};
const listItem = {
hidden: { opacity: 0 },
show: { opacity: 1 }
};
Then i fetch an array of items and save it to my users state. And finally just a simple map to render out some data from that array.
export const Example = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get("https://reqres.in/api/users").then(res => {
setUsers(res.data.data);
});
}, []);
return (
<motion.ul variants={container} initial="hidden" animate="show">
{users.map((item, i) => (
<motion.li key={i} variants={listItem}>
{item.first_name}
</motion.li>
))}
</motion.ul>
);
};
The problem is that those items, while getting rendered does not get staggered and end up getting faded in at the same time. And I'm not exactly sure why. Example of this: https://codesandbox.io/s/wispy-shape-9bfbr?file=/src/Example.js
I can get the transition working if i instead use a static array of items stored in variable and then just use the exact same loop. Like this working example: https://codesandbox.io/s/late-http-vz1s6?file=/src/Example.js
But i need this to work with the array i fetch in the useEffect Hook. Anyone knows how?
Upvotes: 14
Views: 36839
Reputation: 78
Hey guys all you have to do is to apply the staggerChildren to your parent tag
const Box3 = () => {
const boxVariant = {
hidden: {
x: "-100vw", //move out of the site
},
visible: {
x: 0, // bring it back to nrmal
transition: {
delay: 0.5,
when: "beforeChildren", //use this instead of delay
staggerChildren: 0.2, //apply stagger on the parent tag
},
},
};
const listVariant = {
hidden: {
x: -10, //move out of the site
opacity: 0,
},
visible: {
x: 0, // bring it back to nrmal
opacity: 1,
},
};
return (
<div className="box__container">
<motion.div
className="box"
variants={boxVariant}
animate="visible"
initial="hidden"
>
{[1, 2, 3].map((box) => {
{
/* the children is also going to have the same animation as the parent */
}
return (
<motion.li
className="mini__box"
variants={listVariant}
></motion.li>
);
})}
</motion.div>
</div>
);
};
Upvotes: 0
Reputation: 388
I know this has already been answered but still answering it for those who might read it later. So, this is what you need to do.
This is because you don't want to stagger until you have the content or the stagger will run before the content arrives and you won't see it happen.
<React.Fragment>
{users &&
<motion.ul variants={container} initial="hidden" animate="show">
{users.map((item, i) => (
<motion.li key={i} variants={listItem}>
{item.first_name}
</motion.li>
))}
</motion.ul>
}
</React.Fragment>
Upvotes: 22