question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if youā€™re still stuck at the end, weā€™re happy to hop on a call to see how we can help out.

[BUG] Shared layout animations not working when rendered in React portal

See original GitHub issue

1. Read the FAQs šŸ‘‡

2. Describe the bug

Shared layout animations donā€™t animate when:

  • rendered inside a React portal, AND
  • there is an existing motion node that would be normally the parent node of the shared layout animation, but itā€™s not anymore after the animation component gets ā€œteleportedā€ through the portal

Basically the combination of these two factors breaks the shared layout animation ā€” instead, only the ā€œfirstā€ and ā€œlastā€ states of the animation are rendered (without interpolation).

Initially reported in https://github.com/WordPress/gutenberg/pull/40276

3. IMPORTANT: Provide a CodeSandbox reproduction of the bug

A CodeSandbox minimal reproduction will allow us to quickly follow the reproduction steps. Without one, this bug report wonā€™t be accepted.

https://codesandbox.io/s/framer-motion-and-portals-ozvlh3

4. Steps to reproduce

Steps to reproduce the behavior:

  1. Create a component that internally uses shared layout animations via the layoutId prop
  2. Render the component as follows:
// pseudo-code. for a real case example, visit the CodeSandbox link above
<motion.div>
  <PortalBoundary>
    <ComponentThatUsesSharedLayoutAnymations />
  </PortalBoundary>
</motion.div>
  1. Notice how the shared layout animation doesnā€™t animated (it goes from initial to final state of the ā€œanimationā€ without interpolating)
  2. Swap the motion.div wrapper elements with a simple div
  3. The animation works as expected

After some time spent investigating, I believe that the ProjectionNode associated to the element participating in the shared layout animation keeps referencing the wrapper motion.div as its root node, even after the component gets rendered in another part of the dom (via the portal). This could result in buggy behaviour, especially given how ProjectionNodes forward updates via their root nodes.

5. Expected behavior

The shared layout animation works as expected, interpolating smoothly between the initial and final state of the animation.

6. Video or screenshots

https://user-images.githubusercontent.com/1083581/165150804-ae28b242-8c78-4ad8-9c33-b1eba296876d.mp4

7. Environment details

I donā€™t think itā€™s relevant, but I can reproduce the bug on Mac OS Chrome, Mac OS Firefox, Mac OS Safari (all latest versions).

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:8

github_iconTop GitHub Comments

7reactions
tobcommented, Sep 6, 2022

We are experiencing the same bug when trying to use animations inside a modal rendered via portal.

2reactions
birmittcommented, Oct 17, 2022

An easy fix, at least in my case, is to reset the MotionContext. As I understand this context is created by any motion node. Among other information, it propagates the animation variants downstream. My menu is mounted in a portal so I donā€™t need this feature.

// Pseudo code to show the basic setup
<motion.div style={{x: 100}}>
  <MotionContext.Provider value={{}}>
    <MenuButton layoutId="menu"/>
    <Portal>
      <Menu layoutId="menu"/>
    </Portal>
  </MotionContext.Provider>
</motion.div>

The MotionContext created by the motion.div gets directly overwritten with an empty one. Now there is no connection between motion.div and Menu anymore. The shared element animation works perfectly.

This solution may has other implications. I havenā€™t noticed any side-effects so far. For me it generally sounds logical to disconnect a parent motion node from a portaled motion node because they are not in the same visual tree.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Framer Motion & React Portals : No Transitions Occur
To do so, I'm mounting my React components via React Portals. In short, while my components do mount as expected, the animations are...
Read more >
How to Use React Portals in the Real World - Code Frontend
In simple terms - portals allow you to render the component's content into an element that's outside of where the component's content isĀ ......
Read more >
Using React Portals to build a modal - LogRocket Blog
Let's wrap the modal's return JSX with ReactPortal so that the modal is rendered outside of the DOM hierarchy and within the provided...
Read more >
Using React Portals to Render Children Outside the DOM ...
When on is false , the Portal component is not being rendered in the root, so the DOM looks like this. More use...
Read more >
Portals - React
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. ReactDOM.createPortal(child,Ā ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found