skip to Main Content

I’m trying to make a [n sec] countdown using Framer Motion in a React Application, but when I try to change the text displaying on the screen after the [n sec], the countdown gets to the 0 seconds before the text change happens.

Here’s the code that makes that change:

const [status, setStatus] = useState("Waiting...");
const count = useMotionValue(5);
const time = useTransform(count, Math.round);

useEffect(() => {
    const animation = animate(count, 0, { duration: 5 });

    setTimeout(() => {
        setStatus("Finished!");
    }, 5 * 1000);

    return animation.stop;
}, []);

The GitHub repository to reproduce this is linked here: https://github.com/jpfragoso30/jp-framer-sandbox/tree/main

I’ve tried using the onUpdate method for animate to check if it’s a problem of being async

const animation = animate(count, 0, { duration: 5, onUpdate: (value) => { if (value === 0) setStatus("Finished!"); }, });

And the .then for when the animation ends

const animation = animate(count, 0, { duration: 5, }).then(() => setStatus("Finished!"));;

In all of these attempts I’m just getting the same result, the "Finished!" text has a delay, and I don’t think the animation is counting naturally if that makes sense.

2

Answers


  1. Would you try with a promise?

    useEffect(() => {
      const controls = animate(count, 0, { duration: 5 });
      
      controls.then(() => {
        setStatus("Finished!");
      });
    
      return () => controls.stop();
    }, []);
    

    Due to the nature of useState with async functions like animate like this other issue about lag.

    Login or Signup to reply.
  2. Firstly, the method to transform your count value has to be ceiling to start counting at 0, at only go to 0 when you have an absolute zero

    const time = useTransform(count, Math.ceil);
    
    and also, to make the time go "natural", you must declare a "linear" movement
    
    const animation = animate(count, 0, {
                duration: 5,
                ease: "linear",
            }).then(() => setStatus("Finished!"));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search