Skip to content

fix: make Reorder compatible with LazyMotion#3717

Open
raashish1601 wants to merge 1 commit into
motiondivision:mainfrom
raashish1601:codex/2232-reorder-lazymotion
Open

fix: make Reorder compatible with LazyMotion#3717
raashish1601 wants to merge 1 commit into
motiondivision:mainfrom
raashish1601:codex/2232-reorder-lazymotion

Conversation

@raashish1601
Copy link
Copy Markdown

Summary

Reorder.Group and Reorder.Item imported components from the full motion proxy and passed ignoreStrict, which means importing Reorder could eagerly include the full feature bundle and bypass LazyMotion strict checks.

This switches Reorder internals to the lightweight m component 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.tsx reported one existing react-compiler warning in Item.tsx and 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

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 12, 2026

Greptile Summary

This PR switches Reorder.Group and Reorder.Item from the bundled motion proxy to the lightweight m namespace and drops the ignoreStrict bypass, so Reorder no longer eagerly includes the full feature bundle or suppresses LazyMotion strict-mode errors.

  • motion \u2192 m namespace + ignoreStrict removal (Group.tsx, Item.tsx): The m namespace is a static module; components are created at module load time without preloadedFeatures, so they never call loadFeatures. With the old proxy, motion[as] triggered loadFeatures(featureBundle) as a side effect of the first render, initializing drag and layout globally. With the new code, users who only use Reorder (no LazyMotion, no other motion.X components) will find drag and layout silently absent.
  • Missing as tags in m namespace: HTMLElements (and thus ReorderElementTag) includes br, center, meta, noindex, noscript, search, slot, template, and var, which are not exported from m/namespace.ts. Passing any of these as the as prop resolves to undefined at runtime and causes a React "Element type is invalid" error; the old motion proxy handled arbitrary string keys dynamically.

Confidence Score: 3/5

The 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 motion to m removes the implicit loadFeatures(featureBundle) side-effect that the old proxy triggered on first render. Apps using only Reorder without LazyMotion or other motion components will silently lose drag and layout functionality. A subset of TypeScript-valid as values are also missing from the m namespace, yielding undefined components and React crashes for those tags.

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

Filename Overview
packages/framer-motion/src/components/Reorder/Group.tsx Switches from motion proxy to m namespace and removes ignoreStrict; introduces a feature-initialization regression for users who rely solely on Reorder without LazyMotion or other motion components, and silently yields undefined for some valid as values.
packages/framer-motion/src/components/Reorder/Item.tsx Same motionm namespace switch and ignoreStrict removal as Group.tsx; shares the same feature-initialization and missing-element-tag concerns.

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"]
Loading

Reviews (1): Last reviewed commit: "fix: make Reorder use lazy motion compon..." | Re-trigger Greptile

Comment on lines 86 to 90
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> }>
>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Comment on lines 86 to 90
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> }>
>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] "Reorder" is not compatible with "LazyMotion"

1 participant