Intelligence is foundation
Podcast Subscribe
Web Development Monday, 23 March 2026

One Component, Two Places, Zero Compromises

Share: LinkedIn
One Component, Two Places, Zero Compromises

A checkout form that lives in the sidebar on desktop but moves to a modal on mobile - while keeping every input value, every validation error, and every piece of state intact. This breakdown shows how React Portals solve a layout problem most developers hack around instead of fixing properly.

The problem is common. You build a component that works perfectly in one layout. Then responsive requirements come in, and suddenly that component needs to live in a completely different part of the DOM depending on screen size. The naive fix is to render it twice - once for mobile, once for desktop - and try to sync state between them. That's fragile, bug-prone, and fails the moment you have complex state like file uploads or multi-step forms.

The correct fix is simpler. One component instance. Multiple render targets. React Portals handle the DOM positioning. Media query hooks handle the breakpoint logic. State stays in one place because the component only exists once.

How Portals Actually Work

React Portals let you render a component into a DOM node that exists outside your component tree. Normally, React renders children into their parent's DOM node. Portals break that rule. You can render a child into any DOM node you specify - a sidebar, a modal root, a completely different section of the page.

The key insight is that even though the component renders elsewhere in the DOM, it stays in the same place in React's component tree. That means props, context, and event bubbling all work as if the component were still nested normally. You get the layout flexibility of manual DOM manipulation with the state management guarantees of React.

The syntax is straightforward: ReactDOM.createPortal(component, targetNode). You give it the JSX to render and the DOM node to render into. React handles the rest.

The Media Query Hook

Portals handle where to render. You still need to decide when to switch. That's where a media query hook comes in. The pattern is simple: listen for viewport changes, return a boolean that indicates whether you're above or below the breakpoint.

The implementation uses window.matchMedia to register a listener that fires whenever the viewport crosses your breakpoint threshold. On mobile, the hook returns true. On desktop, it returns false. Your component reads that value and decides whether to portal into the modal root or render inline in the sidebar.

This keeps the layout logic declarative. The component doesn't know about sidebars or modals. It just knows: if mobile, use target A. If desktop, use target B. The hook abstracts away the viewport detection. The portal abstracts away the DOM positioning.

Why This Beats Conditional Rendering

The alternative approach - rendering two versions of the component and hiding one with CSS - fails in three ways.

First, you're managing state in two places. Every input change, every validation error, every piece of form state needs to sync between the mobile and desktop versions. That's a bug farm. Miss one sync point and you get phantom errors or lost data.

Second, you're rendering twice as much. React has to maintain two component instances, even though only one is visible. That's wasted memory and wasted reconciliation cycles. On low-end devices, that overhead is real.

Third, refs break. If you're using refs to manage focus, scroll position, or third-party integrations, you now need two ref objects that somehow stay in sync. That's not just hard - it's often impossible. File upload inputs, video players, rich text editors - anything that holds internal state outside React's control - will behave unpredictably when duplicated.

Portals solve all three. One component. One state tree. One ref. It just renders in different places depending on viewport size.

The Context Guarantee

One non-obvious benefit: context providers work across portals. If your checkout form depends on a theme context, a user context, or a cart context, those all flow through correctly even when the component renders into a portal.

This is because portals only affect DOM positioning, not React's component hierarchy. From React's perspective, the component is still nested inside its parent. Context lookups traverse the component tree, not the DOM tree. So even though the checkout form renders into a modal root three levels up in the DOM, it still reads context from its logical parent in the React tree.

This makes portals safe for complex component architectures. You're not breaking encapsulation. You're not losing access to global state. You're just moving the final output to a different place on the page.

When Not to Use This

Portals are the right tool for layout problems where a component needs to move between DOM locations. They're not the right tool for conditional logic - if the mobile and desktop versions have genuinely different behaviour, just render them separately.

They're also overkill if your component is simple. A button that changes text on mobile doesn't need a portal. Just use CSS or a ternary. The portal overhead (setting up the target node, managing the hook) only makes sense when you're preserving complex state.

Finally, portals don't solve server rendering elegantly. The target DOM node has to exist before you can portal into it, which means you need client-side hydration logic to handle the initial render. If you're doing pure SSR, conditional rendering with synced state might actually be simpler.

What This Unlocks

Once you internalise this pattern, you stop compromising on responsive layouts. Checkout forms that move between sidebar and modal. Navigation menus that shift from inline to overlay. Toolbars that reposition based on scroll. All without duplicating components or losing state.

It's the kind of technique that should be more widely known than it is. Most React developers know portals exist. Fewer realise they're the clean solution to a problem they've been hacking around for years.

One component. Two places. Zero compromises. That's what portals give you.

More Featured Insights

Artificial Intelligence
Teaching Models to Learn You - No Extra Data Required
Quantum Computing
Testing Quantum Probability Itself - Not Just Predictions

Today's Sources

arXiv cs.LG
Maximizing mutual information between user-contexts and responses improve LLM personalization with no additional data
arXiv cs.AI
Hyperagents
arXiv cs.LG
Speculating Experts Accelerates Inference for Mixture-of-Experts
TechCrunch
Cursor admits its new coding model was built on top of Moonshot AI's Kimi
arXiv cs.AI
When both Grounding and not Grounding are Bad -- A Partially Grounded Encoding of Planning into SAT (Extended Version)
arXiv cs.AI
Teaching an Agent to Sketch One Part at a Time
arXiv – Quantum Physics
Local asymmetry in interference as a probe of quantum probability
arXiv – Quantum Physics
Assessing Spatiotemporally Correlated Noise in Superconducting Qubits via Pulse-Based Quantum Noise Spectroscopy
Quantum Zeitgeist
Rice University Theory Links Topology to Electron Interactions in Quantum Materials
arXiv – Quantum Physics
Semidefinite block-matrix relaxations for computing quantum correlations
Dev.to
How I Moved a React Component Across the DOM Without Losing Its State - A Checkout Story
AWS Compute Blog
Testing Step Functions workflows: a guide to the enhanced TestState API
Dev.to
#DevWatch - Turning GNOME into a Developer-Aware OS
InfoQ
Spring News Roundup: Third Milestone Releases of Boot, Security, Integration, AI and AMQP
Elementor
10 Best WordPress AI Builders in 2026
Dev.to
Lessons Learned Building Modern Digital Products

About the Curator

Richard Bland
Richard Bland
Founder, Marbl Codes

27+ years in software development, curating the tech news that matters.

Subscribe RSS Feed
View Full Digest Today's Intelligence
Free Daily Briefing

Start Every Morning Smarter

Luma curates the most important AI, quantum, and tech developments into a 5-minute morning briefing. Free, daily, no spam.

  • 8:00 AM Morning digest ready to listen
  • 1:00 PM Afternoon edition catches what you missed
  • 8:00 PM Daily roundup lands in your inbox

We respect your inbox. Unsubscribe anytime. Privacy Policy

© 2026 MEM Digital Ltd t/a Marbl Codes
About Sources Podcast Audio Privacy Cookies Terms Thou Art That
RSS Feed