Skip to content

Commit

Permalink
Fixing AnimatePresence rerenders (#2744)
Browse files Browse the repository at this point in the history
* Adding failing tests

* Fixing rerender

* Undoing test changes
  • Loading branch information
mattgperry authored Jul 27, 2024
1 parent 11523f8 commit 0668c80
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ describe("AnimatePresence", () => {
expect(element).toHaveStyle("transform: translateX(100px)")
})

test("Normal rerenders work as expected", async () => {
const Component = ({ color }: { color: string }) => {
return (
<AnimatePresence>
<div style={{ backgroundColor: color }} />
</AnimatePresence>
)
}

const { container, rerender } = render(<Component color="red" />)
rerender(<Component color="green" />)

expect(container.firstChild).toHaveStyle("background-color: green")
})

test("Animates out a component when its removed", async () => {
const opacity = motionValue(1)

Expand Down
14 changes: 2 additions & 12 deletions packages/framer-motion/src/components/AnimatePresence/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { LayoutGroupContext } from "../../context/LayoutGroupContext"
import { invariant } from "../../utils/errors"
import { useIsomorphicLayoutEffect } from "../../three-entry"
import { useConstant } from "../../utils/use-constant"
import { ComponentKey, arrayEquals, getChildKey, onlyElements } from "./utils"
import { ComponentKey, getChildKey, onlyElements } from "./utils"

/**
* `AnimatePresence` enables the animation of components that have been removed from the tree.
Expand Down Expand Up @@ -137,17 +137,7 @@ export const AnimatePresence: React.FunctionComponent<
nextChildren = exitingChildren
}

nextChildren = onlyElements(nextChildren)

const childrenHaveChanged = !arrayEquals(
nextChildren.map(getChildKey),
renderedChildren.map(getChildKey)
)

if (childrenHaveChanged) {
setRenderedChildren(nextChildren)
}

setRenderedChildren(onlyElements(nextChildren))
setDiffedChildren(presentChildren)

/**
Expand Down
10 changes: 0 additions & 10 deletions packages/framer-motion/src/components/AnimatePresence/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,3 @@ export function onlyElements(children: ReactNode): ReactElement<any>[] {

return filtered
}

export function arrayEquals(a: any[], b: any[]) {
if (a.length !== b.length) return false

for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false
}

return true
}

0 comments on commit 0668c80

Please sign in to comment.