From 9011c7d680cbb1cd7efc0922673430399bbc1536 Mon Sep 17 00:00:00 2001 From: Takeru Chuganji Date: Sat, 29 Jul 2023 09:35:22 +0900 Subject: [PATCH] Explicitly check if animations completed --- .../interfaces/visual-element-target.ts | 12 ++++++++- .../motion/__tests__/animate-prop.test.tsx | 27 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/framer-motion/src/animation/interfaces/visual-element-target.ts b/packages/framer-motion/src/animation/interfaces/visual-element-target.ts index dfcaec86cf..723826d904 100644 --- a/packages/framer-motion/src/animation/interfaces/visual-element-target.ts +++ b/packages/framer-motion/src/animation/interfaces/visual-element-target.ts @@ -43,6 +43,7 @@ export function animateTarget( if (transitionOverride) transition = transitionOverride const animations: AnimationPlaybackControls[] = [] + const promises: (Promise)[] = [] const animationTypeState = type && @@ -101,10 +102,19 @@ export function animateTarget( } animations.push(animation) + promises.push(new Promise((resolve) => { + const subscriptions: (() => void)[] = [] + const unsubscribe = () => subscriptions.forEach((fn) => fn()) + subscriptions.push(value.on('animationComplete', () => { + unsubscribe() + resolve() + })) + subscriptions.push(value.on('animationCancel', unsubscribe)) + })) } if (transitionEnd) { - Promise.all(animations).then(() => { + Promise.all(promises).then(() => { transitionEnd && setTarget(visualElement, transitionEnd) }) } diff --git a/packages/framer-motion/src/motion/__tests__/animate-prop.test.tsx b/packages/framer-motion/src/motion/__tests__/animate-prop.test.tsx index 09430e1ed4..69b1f00240 100644 --- a/packages/framer-motion/src/motion/__tests__/animate-prop.test.tsx +++ b/packages/framer-motion/src/motion/__tests__/animate-prop.test.tsx @@ -136,6 +136,33 @@ describe("animate prop as object", () => { }) return expect(promise).resolves.toBe(300) }) + test("uses the latest styles on subsequent renders", async () => { + const promise = new Promise((resolve) => { + const x = motionValue(0) + const Component = ({ animate }: any) => ( + + ) + const { rerender } = render( + + ) + rerender( + + ) + requestAnimationFrame(() => resolve(x.get())) + }) + return expect(promise).resolves.toBe(20) + }) test("animates to set prop and preserves existing initial transform props", async () => { const promise = new Promise((resolve) => { const onComplete = () => {