When some prop in my component changes in framer motion, I would like to fade that property out, then fade the "new" property value in?
Here's the timeline of the animation as I imagine it:
But the only way I see to do this with framer is to use Timeouts. Is there some way other than using timeouts to achieve this effect?
import { motion } from "framer-motion";
import { useEffect, useState } from "react";
import "./styles.css";
export default function App() {
const [seconds, setSeconds] = useState(0);
const [anim, setAnim] = useState("in");
useEffect(() => {
const interval = setInterval(() => {
setSeconds((seconds) => seconds + 1);
setAnim("in");
setTimeout(() => {
setAnim("out");
}, 500);
}, 1000);
return () => clearInterval(interval);
}, []);
const variants = {
out: {
opacity: 0
},
in: {
opacity: 1,
transition: {
duration: 0.5
}
}
};
return (
<motion.div
animate={anim}
variants={variants}
className="App"
style={{ fontSize: 100 }}
>
{seconds}
</motion.div>
);
}
You can do this with AnimatePresence.
Wrap your motion.div
with an AnimatePresence
tag, and use the seconds
as a unique key for your div. The changing key will trigger AnimatePresence
to animate the div in and out each time it changes (because new key means it's a different element).
To get this to work, you'll need to define your animations on the initial
, animate
, and exit
props.
You'll also want to be sure to set the exitBeforeEnter
prop on AnimatePresence
so the fade out animation completes before the fade in starts.
export default function App() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds((seconds) => seconds + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<AnimatePresence exitBeforeEnter>
<motion.div
initial={{opacity:0}}
animate = {{opacity: 1, transition:{duration: 0.5}}}
exit={{opacity: 0 }}
className="App"
style={{ fontSize: 100 }}
key={seconds}
>
{seconds}
</motion.div>
</AnimatePresence>
);
}