Skip to content

[BUG] useTransform does not reflect update of chained MotionValues #2280

Open

Description

@ali-idrizi

I am building a complicated animation, where a transform depends on several motion values. These values are sometimes repeating, so I extracted them to separate motion values, which are calculated using useTransform. I have managed to reproduce the issue with a very simple example:

const a = useMotionValue(0);
const aHalf = useTransform(a, (a) => a / 2);
const aQuarter = useTransform(aHalf, (h) => h / 2);

const result = useTransform([a, aQuarter], ([a, aQuarter]) => {
  // the aQuarter MotionValue is eventually updated to `25`, but it is never reported here. This will log `100, 0` instead of `100, 25`
  console.log({ a, aQuarter });
  return a + aQuarter;
});

useMotionValueEvent(a, "change", (v) => console.log("a", "change", v));
useMotionValueEvent(aQuarter, "change", (v) => console.log("aQuarter", "change", v));
useMotionValueEvent(result, "change", (v) => console.log("result", "change", v));

React.useEffect(() => {
  setTimeout(() => a.set(100), 500);
}, []);

Here is a Codesandbox of the same: https://codesandbox.io/s/framer-motion-enter-animation-forked-4jfkdc?file=/src/App.tsx

If you check the logs you will notice:

a change 100
{a: 100, aQuarter: 0}
result change 100
aQuarter change 25

As you can see, the useTransform for result never logs the aQuarter value of 25, while the same is being reported by useMotionValueEvent. This issue results in the transform outputting an incorrect value for result of 100, while it is supposed to be 125.

Activity

  1. piotrnajda3000 commented on Aug 20, 2024

    @piotrnajda3000

    I concur.

    I have the following transform:

    const { scrollYProgress } = useScroll({
        target: containerRef,
        offset: ["start end", "end end"],
     });
      
    const progress = useTransform(scrollYProgress, [0, 0.3, 0.7], [0, 0, 1]);
    
    const vidScale = useTransform(
        progress,
        [0, 1],
        [1, 9],
      );
      
    // even though progress will be 1, vidScale won't reach it's target. 
    progress.on("change", (v) => { console.log(v, vidScale.get() });
    

    Even though progress reaches 1, headingScale is shy of it's needed target (9 in this example).

  2. mordechaim commented on Oct 13, 2026

    @mordechaim

    Ran into this issue today, chained transforms 3 levels deep skipped a frame

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions