Sitemap
Hex Shift

Hex Shift

Tutorial guides on Phoenix Liveview, Python, Rust, React, Tailwind CSS, HEex, Websockets, Elixir, Containerd, Mojo, Docker, Markdown, vibe coding and more.

Stop Abusing React Portals Before They Destroy Your Codebase

7 min readAug 17, 2025
Press enter or click to view image in full size

React portals are one of those features developers love to name drop in conversations about advanced React patterns. They carry the allure of something sophisticated, almost magical. The premise is straightforward enough: portals let you render children into a DOM node that exists outside the parent component’s hierarchy. It is a simple API that looks like it solves a host of problems. Yet time and again developers discover that working with portals feels harder than it should and most of us misuse them.

When portals were introduced in React 16 they were heralded as the missing piece for modals, tooltips and popovers. Finally we had a first class way of breaking out of parent containers without hacks. But in practice the story has not been that smooth. What people get wrong is not just about syntax mistakes. The missteps run deeper and reveal that portals require us to think about React’s rendering model, the DOM and even accessibility in ways that many skip over. After reading this article, make sure you check out Using React Portals Like a Pro.

The first misconception is the belief that portals exist to fix z-index issues. A surprising number of tutorials and blog posts pitch portals as the tool you use when your modal ends up stuck behind another div. Developers are encouraged to throw the modal into a portal and magically the stacking context is solved. While this works sometimes it papers over the real issue. Z-index conflicts are usually a symptom of CSS architecture problems. Using a portal to move an element into a different part of the DOM tree can solve the immediate pain but it leaves the underlying design untouched. Over time the codebase fills up with portals sprinkled everywhere and the DOM becomes fragmented. The solution ends up harder to reason about than the problem it replaced.

Another frequent pitfall comes from confusing ownership of state. The mental model of React emphasizes that components are self contained. But portals break this intuition. When a child is rendered into a portal its parent component still owns its React hierarchy but visually the child lives elsewhere in the DOM. This dual reality confuses event handling. Developers often expect events to bubble based on the DOM structure but in React they bubble through the React tree. This leads to head scratching bugs where click handlers appear not to fire or where stopPropagation does not behave as expected. The frustration here is that portals obey React’s rules rather than the DOM’s and developers who rely on their browser instincts get tripped up.

Accessibility is another casualty of portal misuse. The canonical example of a portal is the modal dialog. But a modal that is simply portaled into document.body is not automatically accessible. Screen readers need focus management. The tab order needs to be trapped within the modal. ARIA roles must be set correctly. Developers frequently assume that because the modal renders correctly on screen the job is done. In reality the portal made the technical rendering possible but the accessibility story remains a separate challenge. The number of production apps with inaccessible modals is staggering and portals are often to blame because they gave a false sense of completion.

Server side rendering adds yet another wrinkle. On the client a portal can mount into a target DOM node with no issue. On the server that target does not exist in the same way. Many developers forget to guard portal rendering or to ensure consistent markup between client and server. The result is hydration mismatches where React throws warnings and the UI behaves inconsistently. Once again portals demand a deeper understanding of React’s rendering lifecycle than many developers have when they first adopt them.

Then there is testing. Portals complicate unit and integration tests. A modal that renders via a portal will not show up as a child of the component under test. Instead it lives in some global DOM node. Developers who rely on test libraries without configuring a container for portals find themselves writing brittle selectors or resorting to hacks. Some test setups require explicitly appending a target div to the document before rendering tests. Others rely on mocking portal creation entirely. This complexity reveals that portals are not just another component pattern. They are a bridge between React’s virtual tree and the raw DOM. Without a strategy tests become fragile and error prone.

There is also the subtle problem of styling. When a component is portaled it no longer inherits CSS rules that depend on DOM ancestry. Developers expect selectors like .parent .child to work even when the child is rendered in a portal. But the portal has broken that relationship. Unless styles are written with this in mind the UI suddenly looks wrong. Workarounds often involve passing down class names or relying on global styles. Both approaches compromise the encapsulation we strive for in component design. In other words the styling headache exposes the architectural tradeoff that portals introduce.

The irony is that the more portals are used the more the benefits of component isolation erode. Instead of components being predictable building blocks the DOM becomes a patchwork of portaled fragments. Tooltips here modals there dropdowns scattered across document.body. Debugging such an app means scanning unrelated parts of the DOM tree to understand what is happening. Performance profiling suffers as well because elements that appear visually related are rendered into different parts of the page. Developers lose the one to one mapping between component hierarchy and DOM structure that is supposed to make React predictable.

Get Hex Shift’s stories in your inbox

Join Medium for free to get updates from this writer.

What is striking is how rarely these problems are acknowledged when portals are introduced to beginners. Most tutorials offer a one paragraph explanation and a code snippet. Few dwell on the broader consequences. This leaves many developers convinced that portals are trivial when in fact they demand architectural forethought. The result is widespread misuse and projects that grow increasingly brittle over time.

To understand why this happens we have to revisit why React was created. React’s genius was to give us a declarative way to describe UI components as functions of state. The DOM became an implementation detail managed by React. Portals disrupt this abstraction because they deliberately expose DOM placement as a concern again. Suddenly developers must juggle both React’s hierarchy and the physical DOM hierarchy. The abstraction is leaky. Many developers do not realize they are back in the land of manual DOM management until they hit the walls described above.

Of course there are legitimate use cases where portals shine. A tooltip that must break out of an overflow hidden container. A context menu that must position itself at the viewport level. A modal that should always render above other content. In these cases the portal API is indispensable. The danger lies in treating portals as a quick fix rather than as a last resort. Every portal added to an application increases cognitive load and architectural complexity. Unless justified by a clear need the cost often outweighs the benefit.

Another underappreciated challenge is coordinating portals with animation libraries. Many React developers reach for libraries like Framer Motion or React Spring. When components animate within the same hierarchy everything behaves as expected. But when a component animates into or out of a portal synchronization becomes tricky. The animation may start before the portal is mounted or continue after the portal is unmounted. Without careful orchestration you end up with flickers or broken transitions. Once again the portal complicates what should have been straightforward.

If portals are to be used responsibly developers need to cultivate a discipline of questioning whether they are truly necessary. More often than not CSS layering strategies flexbox or grid layouts or simply restructuring the component tree can solve the underlying problem without reaching for a portal. Only when these options fail should a portal be considered. Even then one must plan for accessibility testing and maintainability. Treating portals as a shortcut is what creates the chaos.

One more subtle trap is assuming that portals automatically integrate well with context. While context values are accessible inside a portal because it remains in the React tree developers sometimes misunderstand how that plays out. They expect the portaled component to inherit not just state but also DOM based context such as relative positioning or containment. This disconnect can be jarring. It reinforces the lesson that React context and DOM context are separate ideas. Confusing the two leads to unexpected behavior.

The ultimate takeaway is that portals are a double edged sword. They empower us to break the rules of the DOM when necessary but they demand a level of respect that many skip. Misused they erode the predictability and composability that React promises. Used with care they can elegantly solve otherwise intractable layout problems. The challenge is cultivating that restraint and teaching new developers that portals are not a first class solution for everything that looks hard.

React’s community has matured enough to acknowledge that not every feature is pure sugar. Some features are low level escape hatches intended for edge cases. Portals fall squarely in that category. They are not designed to be sprinkled throughout every project. They are a scalpel not a hammer. The projects that thrive are the ones that understand this distinction and keep portals rare and purposeful.

So the next time you find yourself about to reach for a portal ask whether the problem is truly unsolvable without it. Ask whether you are masking deeper CSS or layout issues. Ask whether accessibility and testing have been thought through. If the answer to these questions is no then the portal is not your friend. The cost may be hidden at first but it will surface later in harder debugging sessions slower onboarding of new developers and brittle code.

Portals are not inherently bad. They are simply more complicated than they appear. The biggest mistake developers make is treating them as simple. The truth is that portals demand a maturity of thought about how React and the DOM intersect. Pretending otherwise only leads to pain.

If you want to dive deeper into mastering this subject I have created a comprehensive guide that unpacks practical strategies patterns and pitfalls around portals in real projects. You can get it here: Using React Portals Like a Pro. It goes beyond the basics and gives you the tools to use portals confidently without falling into the traps we have explored above.

--

--

Hex Shift
Hex Shift

Written by Hex Shift

Tutorial guides on Phoenix Liveview, Python, Rust, React, Tailwind CSS, HEex, Websockets, Elixir, Containerd, Mojo, Docker, Markdown, vibe coding and more.