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.

Support for changing a Portal's container without remounting children?

See original GitHub issue

(This is related to https://github.com/facebook/react/issues/3965.)

I’m working on a project with a lot of globally unique component instances. (In other words, their keys are essentially database IDs.) It also has DnD functionality. For reordering, everything is fine, but moving an instance from one parent to another causes a complete re-render of the instance.

Instead of moving the nodes around myself, I was thinking of using Portals. Each instance has a prop for which element ID they should render inside. Then, to reparent them, it’d be a simple case of passing a different element ID. (I’m using Redux, so it’d just be a string in the state.)

However, changing a Portal’s container node also causes a complete re-render of everything passed to ReactDOM.createPortal. (See this CodePen.)

Would it be possible to skip this re-rendering and effectively move the Portal contents instead?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:38
  • Comments:28 (8 by maintainers)

github_iconTop GitHub Comments

22reactions
pimterrycommented, Aug 26, 2019

@gaearon @benwiley4000 I hit this too & fixed it for myself. Rather than put together an example, I’ve turned the basic pattern you’re describing into a library you can use to solve this properly.

It’s effectively the concept defined above, with a few additions, and lets you define some content in one place, render & mount it there once, then place it elsewhere and move it later (potentially out of the page entirely, and back) all without remounting or necessarily rerendering.

I’m calling it reverse portals, since it’s the opposite model to normal portals: instead of pushing content from a React component to distant DOM, you define content in one place, then declaratively pull that DOM into your React tree elsewhere. I’m using it in production to reparent expensive-to-initialize components, it’s working very nicely for me!

Repo is over here: https://github.com/httptoolkit/react-reverse-portal. Let me know if it works for you!

15reactions
gaearoncommented, Apr 24, 2019

We had a similar problem and solved it in userland with a combination of portals, context, and refs. It’s a bit convoluted but it works. The idea is that you have state and a “node manager” live at the top. Your leaf component, when it mounts, passes its “leaf div” up the context to the “node manager”. In return, the “node manager” gives the leaf component a node to portal into. That node would always be the same. Node manager would create it once. Initially, node manager would attach it to the leaf’s own “leaf div”. But it can also detach it and attach it somewhere else without recreating the element. From leaf’s point of view, it always renders the portal into the same node. But the thing at the top can move that node from an actual div (originally in the leaf) to any other div on the page. Instead of reparenting the portal itself, we always portal into the same node, but that node itself is moved in the document imperatively wherever we need.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Prevent child component from unmounting and remounting if ...
You'll just need to change the order of the component tree, leveraging the render props pattern: Child (heavy) component is rendered first.
Read more >
Learn React Portals by example - LogRocket Blog
Check out this step-by-step breakdown of a common use case for React Portal and learn how to develop a tooltip component from scratch....
Read more >
Using React Portals to Render Children Outside the DOM ...
TL;DR: Mounting is the moment the element is inserted into the DOM. When the component unmounts we want to remove the child to...
Read more >
Avoid unnecessary remounting of DOM elements in React
I ran into a strange problem while trying to use React's built-in animation API to fade in/out DOM elements when they enter/exit the...
Read more >
Portals - React
A typical use case for portals is when a parent component has an overflow: hidden or z-index style, but you need the 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