fix: make Reorder compatible with LazyMotion#3717
Conversation
Greptile SummaryThis PR switches
Confidence Score: 3/5The change achieves its LazyMotion compatibility goal but introduces a feature-initialization gap for any app that uses Reorder as its sole animation primitive without LazyMotion. Switching from Both Group.tsx and Item.tsx share the same two concerns and should be reviewed together. The m/namespace.ts and m/elements.ts exports are relevant context for the missing-tag issue. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User renders Reorder.Group / Reorder.Item] --> B{Which namespace?}
B -->|OLD: motion proxy| C["motion[as] via JS Proxy"]
C --> D["createMotionComponent(as, undefined, featureBundle, ...)"]
D --> E["loadFeatures(featureBundle) called as side effect"]
E --> F["Drag + Layout features globally initialized"]
F --> G["Component renders with full feature set"]
B -->|NEW: m namespace| H["m[as] — static lookup"]
H --> I{Tag in m namespace?}
I -->|Yes - common tags| J["Returns pre-created minimal component"]
I -->|No - br, center, meta, search, etc.| K["Returns undefined → React crash"]
J --> L{Features already loaded?}
L -->|Yes - via LazyMotion or another motion component| M["✅ Renders correctly"]
L -->|No - Reorder used alone without LazyMotion| N["⚠️ Drag/Layout silently missing"]
Reviews (1): Last reviewed commit: "fix: make Reorder use lazy motion compon..." | Re-trigger Greptile |
| const Component = useConstant( | ||
| () => motion[as as keyof typeof motion] | ||
| () => m[as as keyof typeof m] | ||
| ) as FunctionComponent< | ||
| React.PropsWithChildren<HTMLMotionProps<any> & { ref?: React.Ref<any> }> | ||
| > |
There was a problem hiding this comment.
Feature initialization regression for non-LazyMotion users
In the old code, useConstant(() => motion[as]) triggered the Proxy getter, which called createMotionComponent(as, undefined, featureBundle, createDomVisualElement), which in turn called loadFeatures(featureBundle) as a side effect — initializing drag, layout, and gesture features globally on first render. With the new code, m[as] just returns a pre-created component that was built without preloadedFeatures, so loadFeatures is never called through Reorder's render path. Users who rely on Reorder as their only animation primitive (no LazyMotion, no motion.div / m.div elsewhere in the tree) will silently get non-functional drag and layout because the feature registry is never populated.
| const Component = useConstant( | ||
| () => motion[as as keyof typeof motion] | ||
| () => m[as as keyof typeof m] | ||
| ) as FunctionComponent< | ||
| React.PropsWithChildren<HTMLMotionProps<any> & { ref?: React.Ref<any> }> | ||
| > |
There was a problem hiding this comment.
m namespace doesn't cover all valid ReorderElementTag values
ReorderElementTag is typed as keyof HTMLElements, which includes br, center, meta, noindex, noscript, search, slot, template, and var. None of these are exported from the m namespace, so m[as as keyof typeof m] evaluates to undefined for any of those tags. useConstant then caches undefined, and React will throw "Element type is invalid… got: undefined" at render time. The old motion proxy handled any string key dynamically, so this is a runtime regression for the (admittedly unusual) case where as is set to one of those elements. The same issue exists in Item.tsx.
Summary
Reorder.GroupandReorder.Itemimported components from the fullmotionproxy and passedignoreStrict, which means importing Reorder could eagerly include the full feature bundle and bypassLazyMotion strictchecks.This switches Reorder internals to the lightweight
mcomponent namespace and removes the strict-mode bypass so Reorder behaves like other LazyMotion-compatible components.Fixes #2232.
Validation
./node_modules/.bin/eslint packages/framer-motion/src/components/Reorder/Group.tsx packages/framer-motion/src/components/Reorder/Item.tsxreported one existingreact-compilerwarning inItem.tsxand no errors./node_modules/.bin/jest --runInBand --runTestsByPath packages/framer-motion/src/components/Reorder/__tests__/index.test.tsx --config <temporary Windows resolver config>passed 3 tests