framer / motion

Open source, production-ready animation and gesture library for React
https://framer.com/motion
MIT License
23.87k stars 809 forks source link

[BUG] m is not a function when importing from 'framer-motion/m' and using m('button') syntax #2786

Closed jakeleboeuf closed 2 months ago

jakeleboeuf commented 2 months ago

1. Read the FAQs 👇

2. Describe the bug

m is not a function when importing m from the new framer-motion/m entry and using the Custom component invocation like m('button').

Moving to the new entry might not be necessary for my use case unless there is a plan to deprecate that import path and move entirely to framer-motion/m (I'm already handling the 'use client;' directive on in my lib's build step).

Codesandbox reproductions

3. IMPORTANT: Provide a CodeSandbox reproduction of the bug

https://codesandbox.io/p/sandbox/main-entry-framer-motion-custom-component-11-3-30-5fmghs

4. Steps to reproduce

Steps to reproduce the behavior:

  1. Go to the codesandbod
  2. Look at the preview
  3. See error

5. Expected behavior

When importing m from the new framer-motion/m entry, it should work like normal :)

🚫 Not working

import * as m from 'framer-motion/m';

function MyButton({ as = 'button', ...props }) {
  const Comp = m(as);

  return <Comp {...props} />
};

✅ Working

import { m } from 'framer-motion';

function MyButton({ as = 'button', ...props }) {
  const Comp = m(as);

  return <Comp {...props} />
};

6. Video or screenshots

image

7. Environment details

If applicable, let us know which OS, browser, browser version etc you're using.

FAQs

React Server Components "use client" error

If you're importing motion or m into a React Server Component environment, ensure you're importing from framer-motion/client instead of framer-motion.

import * as motion from "framer-motion/client"
import * as m from "framer-motion/m"

Framer Motion won't install

Different versions of Framer Motion are compatible with different versions of React.

React 19: 12.0.0-alpha.0 or higher React 18: 7.0.0 to 11.x React 17: 6.x or lower

height: "auto" is jumping

Animating to/from auto requires measuring the DOM. There's no perfect way to do this and if you have also applied padding to the same element, these measurements might be wrong.

The recommended solution is to move padding to a child element. See this issue for the full discussion.

Preact isn't working

Framer Motion isn't compatible with Preact.

AnimatePresence isn't working

Have all of its immediate children got a unique key prop that remains the same for that component every render?

// Bad: The index could be given to a different component if the order of items changes
<AnimatePresence>
    {items.map((item, index) => (
        <Component key={index} />
    ))}
</AnimatePresence>
// Good: The item ID is unique to each component
<AnimatePresence>
    {items.map((item, index) => (
        <Component key={item.id} />
    ))}
</AnimatePresence>

Is the AnimatePresence correctly outside of the controlling conditional? AnimatePresence must be rendered whenever you expect an exit animation to run - it can't do so if it's unmounted!

// Bad: AnimatePresence is unmounted - exit animations won't run
{
    isVisible && (
        <AnimatePresence>
            <Component />
        </AnimatePresence>
    )
}
// Good: Only the children are unmounted - exit animations will run
<AnimatePresence>{isVisible && <Component />}</AnimatePresence>
mattgperry commented 2 months ago

Can you change this to m.create() in Motion 11.5

Also move outside the render function otherwise you're making a new component every render