motiondivision / motion

A modern animation library for React and JavaScript
https://motion.dev
MIT License
25.84k stars 849 forks source link

[BUG] AnimatePresence popLayout doesn't work when component is wrapped #2799

Closed jeffijoe closed 2 months ago

jeffijoe commented 2 months ago

1. Read the FAQs πŸ‘‡

βœ…

2. Describe the bug

When wrapping an item in a component, popLayout no longer works.

  <AnimatePresence mode={popLayout ? "popLayout" : "sync"}>
    {items.map((id) => (
      <Item
        key={id}
        theKey={id}
        onRemove={() => {
          const newItems = [...items];
          removeItem(newItems, id);
          setItems(newItems);
        }}
      />
    ))}
  </AnimatePresence>

//

// simple wrapper
function Item({ theKey, onRemove }) {
  return (
    <m.li
      layout
      // this doesn't seem to work either
      key={theKey}
      animate={{ scale: 1, opacity: 1 }}
      exit={{ scale: 0.8, opacity: 0 }}
      transition={{ type: "spring" }}
      onClick={onRemove}
    />
  );
}

3. IMPORTANT: Provide a CodeSandbox reproduction of the bug

https://codesandbox.io/p/sandbox/framer-motion-animatepresence-poplayout-mode-forked-9hzkmr?file=%2Fsrc%2FApp.tsx

4. Steps to reproduce

Steps to reproduce the behavior:

  1. Go to the sandbox
  2. Click on popLayout
  3. Remove an item
  4. Observe that popLayout isn't working

5. Expected behavior

popLayout should work as expected despite having wrapped the component.

6. Video or screenshots

See sandbox.

7. Environment details

macOS, Chrome, React 19 RC, Framer Motion 12 Alpha 1

jeffijoe commented 2 months ago

I missed the very important note in the docs about having to forwardRef the immediate children of <AnimatePresence>, closing.