<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Shivam Ranjan Pandey</title>
    <description>The latest articles on Forem by Shivam Ranjan Pandey (@shivuser).</description>
    <link>https://forem.com/shivuser</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F548576%2F8b1e1f55-3008-47c9-96ef-a44721ab1400.jpeg</url>
      <title>Forem: Shivam Ranjan Pandey</title>
      <link>https://forem.com/shivuser</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shivuser"/>
    <language>en</language>
    <item>
      <title>How We Made Our Canvas Application 30x Faster: A Deep Dive into Performance Engineering</title>
      <dc:creator>Shivam Ranjan Pandey</dc:creator>
      <pubDate>Wed, 17 Dec 2025 08:02:42 +0000</pubDate>
      <link>https://forem.com/shivuser/how-we-made-our-canvas-application-30x-faster-a-deep-dive-into-performance-engineering-2f8p</link>
      <guid>https://forem.com/shivuser/how-we-made-our-canvas-application-30x-faster-a-deep-dive-into-performance-engineering-2f8p</guid>
      <description>&lt;p&gt;&lt;strong&gt;Building enterprise-grade software that handles 10,000+ elements without breaking a sweat&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem We Faced
&lt;/h2&gt;

&lt;p&gt;Picture this: You're building a complex canvas-based design tool. Your users need to create intricate screens with thousands of elements: shapes, buttons, connectors, widgets, and real-time data displays.&lt;/p&gt;

&lt;p&gt;Everything seemed fine during development. Then one day, a tester dragged a group of 50 elements across the screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The browser crashed. Out of memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That was our wake-up call. We dug into the Chrome DevTools memory profiler and discovered something alarming: every drag operation was creating new objects that never got garbage collected. After just a few minutes of normal use, memory usage had ballooned from 100MB to over 2GB.&lt;/p&gt;

&lt;p&gt;But the memory leak was just the tip of the iceberg. As we investigated further, we found performance issues everywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dragging grouped elements caused the UI to freeze&lt;/li&gt;
&lt;li&gt;Switching between screens felt like loading a new application&lt;/li&gt;
&lt;li&gt;Undo/redo was duplicating entire state trees&lt;/li&gt;
&lt;li&gt;Real-time data updates were blocking the main thread&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sound familiar? If you've ever built a complex canvas application with React, you've probably hit these walls too.&lt;/p&gt;

&lt;p&gt;Here's how we fixed it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding the Root Causes
&lt;/h2&gt;

&lt;p&gt;Before diving into solutions, we needed to understand &lt;em&gt;why&lt;/em&gt; things were slow. After profiling our application, we identified several performance killers:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The "Check Everything" Problem
&lt;/h3&gt;

&lt;p&gt;Every frame, we were checking all 10,000 elements to see which ones were visible. That's O(n) complexity—linear time that grows with every element added.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The "Update Everything" Problem
&lt;/h3&gt;

&lt;p&gt;When one element changed, React was re-rendering components that had nothing to do with that change. Our state management was too coarse-grained.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The "Remember Everything" Problem
&lt;/h3&gt;

&lt;p&gt;We were keeping all screens loaded in memory, even ones the user hadn't looked at in hours. And our undo history was growing without bounds.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The "Clone Everything" Problem
&lt;/h3&gt;

&lt;p&gt;Every state update was deep-cloning entire data structures, even when we only changed one property on one element.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The "Search Everything" Problem
&lt;/h3&gt;

&lt;p&gt;Finding which elements belonged to a group, or which data binding belonged to which component, required scanning through entire arrays every single time.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solutions: 15 Optimizations That Changed Everything
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🌳 Spatial Indexing with R-Trees
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; With 10,000 elements, checking which ones are visible = scanning all 10,000 elements. Every. Single. Frame.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; We implemented an R-Tree—a spatial data structure that organizes elements by their position on the canvas. Think of it like a library catalog system, but for 2D space.&lt;/p&gt;

&lt;p&gt;Instead of asking "Is element #4,532 visible?" 10,000 times, we now ask "What's in this rectangular area?" once. The R-Tree answers in O(log n) time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt; Viewport queries went from ~500ms to ~15ms. That's a &lt;strong&gt;33x improvement&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before: Check 10,000 elements → 500ms
After:  Query R-Tree → 15ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🔍 Flat Indexing for O(1) Lookups
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Finding all elements in a group meant scanning the entire element array. Finding a data binding in our component tree meant traversing the whole tree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; We built flat indexes—simple JavaScript Maps that give us instant lookups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;groupId → Set of element IDs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;elementId → groupId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tagId → exact location in tree&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt; Group operations went from O(n) array scans to O(1) hash lookups. Moving a group of 50 elements is now instant, not sluggish.&lt;/p&gt;




&lt;h3&gt;
  
  
  💾 Smart Memory Management with Lazy Loading
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Loading a project with 10 screens × 1,000 elements = 10,000 elements in memory. Most of them sitting there unused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; We built a lazy loading architecture with "cold storage" capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Active screen:&lt;/strong&gt; Full data in memory (Zustand store)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inactive screens:&lt;/strong&gt; Just metadata (element count, last modified)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cold storage:&lt;/strong&gt; Full data persisted to browser storage, loaded on-demand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We've built the infrastructure using &lt;strong&gt;IndexedDB&lt;/strong&gt;—a browser-native database API that can store hundreds of MBs (unlike localStorage's 5MB limit). This enables offline persistence and fast screen switching for large projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt; ~90% memory reduction potential. Screens load in ~50ms when needed.&lt;/p&gt;




&lt;h3&gt;
  
  
  📦 Transaction Batching
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; This was the root cause of our memory leak. Dragging a group of 50 elements across the screen = 50 state updates per frame = 50 history snapshots per frame. At 60fps, that's 3,000 state copies per second. Each copy was a deep clone of the entire element array. No wonder we ran out of memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; We implemented a two-phase commit pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;During drag:&lt;/strong&gt; Updates happen in local state only (no store mutations)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On drag end:&lt;/strong&gt; Single batched update to the store = single history entry&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;50 elements × 60fps drag = &lt;strong&gt;1 history entry&lt;/strong&gt; (vs 3,000 per second)&lt;/li&gt;
&lt;li&gt;Memory leak: &lt;strong&gt;Completely eliminated&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Update time: &lt;strong&gt;~4ms batched vs ~200ms individual&lt;/strong&gt; (50x faster)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🎯 Selective Zustand Subscriptions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; A component subscribing to the store re-renders on ANY state change, even unrelated ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Granular selectors that subscribe to exactly what each component needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Bad: Re-renders when ANYTHING changes&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Good: Re-renders only when activeTool changes&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;activeTool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activeTool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Better: Pre-built optimized hooks&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;activeTool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useActiveTool&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;canUndo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canRedo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useHistoryState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt; Components that used to re-render 100x per second now re-render only when their specific data changes.&lt;/p&gt;




&lt;h3&gt;
  
  
  🖼️ Viewport Culling
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Rendering 10,000 elements when only 100 are visible wastes GPU cycles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Using our spatial index, we now render only what's visible (plus a small buffer for smooth scrolling).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Culling ratio: ~90% for large canvases&lt;/li&gt;
&lt;li&gt;Query time: &amp;lt;1ms&lt;/li&gt;
&lt;li&gt;GPU load: Dramatically reduced&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ⏱️ History Size Limits
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Unlimited undo history = memory growing forever. After a long editing session, the browser would crash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Circular buffer pattern—we keep the last 50 history states and discard older ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt; Memory usage is now bounded. No more crashes after long sessions.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔄 Structural Sharing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Every state update was doing &lt;code&gt;JSON.parse(JSON.stringify(tree))&lt;/code&gt;—deep cloning the entire project tree even to change one property.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Immutable updates with structural sharing. We only clone the nodes on the path to what changed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before: Clone EVERYTHING&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newTree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// O(n)&lt;/span&gt;

&lt;span class="c1"&gt;// After: Clone only the path&lt;/span&gt;
&lt;span class="c1"&gt;// If we're updating node at depth 3, we clone 3 nodes, not 10,000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone time: O(depth) vs O(n)&lt;/li&gt;
&lt;li&gt;Memory: ~95% reduction for deep trees&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🏷️ Real-Time Data Updates
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Our application receives hundreds of data value updates per second from external sources. Each update was traversing the entire component tree to find the binding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Flat data index:&lt;/strong&gt; Build once when project loads, O(1) lookups forever&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batched updates:&lt;/strong&gt; Collect updates for 100ms, apply all at once&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate cache:&lt;/strong&gt; Data values stored separately from tree structure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt; Data updates went from blocking the UI to being imperceptible.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Numbers Don't Lie
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Selection (10k elements)&lt;/td&gt;
&lt;td&gt;~500ms&lt;/td&gt;
&lt;td&gt;~15ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;33x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Screen switch&lt;/td&gt;
&lt;td&gt;~2000ms&lt;/td&gt;
&lt;td&gt;~50ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;40x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Group drag (50 elements)&lt;/td&gt;
&lt;td&gt;~100ms&lt;/td&gt;
&lt;td&gt;~4ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;25x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory (10 screens)&lt;/td&gt;
&lt;td&gt;~400MB&lt;/td&gt;
&lt;td&gt;~40MB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;90% reduction&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data update latency&lt;/td&gt;
&lt;td&gt;~50ms&lt;/td&gt;
&lt;td&gt;&amp;lt;1ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;50x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Measure First, Optimize Second
&lt;/h3&gt;

&lt;p&gt;We didn't guess where the problems were. We profiled, identified bottlenecks, and targeted our efforts.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Data Structures Matter
&lt;/h3&gt;

&lt;p&gt;The right data structure (R-Tree, flat indexes, Maps) can turn O(n) operations into O(1) or O(log n). This is Computer Science 101, but it's easy to forget when you're deep in React components.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Batch Everything
&lt;/h3&gt;

&lt;p&gt;Whether it's state updates, history entries, or network requests—batching almost always wins.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Be Lazy (In a Good Way)
&lt;/h3&gt;

&lt;p&gt;Don't load data until you need it. Don't render elements until they're visible. Don't clone objects until they change.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Granularity is Your Friend
&lt;/h3&gt;

&lt;p&gt;Coarse-grained state management is easy to write but hard to scale. Fine-grained subscriptions take more thought upfront but pay dividends at scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Building performant canvas applications at scale is challenging, but it's not magic. It's about understanding where time and memory are being spent, and applying well-known computer science principles to solve those specific problems.&lt;/p&gt;

&lt;p&gt;The techniques we've shared here are universal. If you're building any complex canvas application—a design tool, a diagramming app, a game level editor, or a dashboard builder—these same patterns will help you scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The best performance optimization is the one that makes your users forget they're using software at all.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;#React #Canvas #Engineering #Optimization #JavaScript #TypeScript&lt;/p&gt;

</description>
      <category>performance</category>
      <category>react</category>
      <category>typescript</category>
      <category>datastructures</category>
    </item>
    <item>
      <title>Creating a reusable Modal component inside React  with Portals</title>
      <dc:creator>Shivam Ranjan Pandey</dc:creator>
      <pubDate>Mon, 04 Jan 2021 16:28:19 +0000</pubDate>
      <link>https://forem.com/shivuser/creating-a-reusable-modal-component-inside-react-with-portals-38m1</link>
      <guid>https://forem.com/shivuser/creating-a-reusable-modal-component-inside-react-with-portals-38m1</guid>
      <description>&lt;h2&gt;
  
  
  During making of any web application Modals are the best way to display information or any feature to user without navigating user to different page.
&lt;/h2&gt;

&lt;p&gt;We will be using &lt;a href="https://www.npmjs.com/package/reactstrap"&gt;reactstrap&lt;/a&gt; for displaying a  modal.&lt;/p&gt;

&lt;p&gt;Our main requirements are :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Making it generic enough to be used whereever we want to 
display a Modal.&lt;/li&gt;
&lt;li&gt;Opening a Modal from a nested child component / maybe even from
another modal itself&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The second requirement can be handled using the &lt;a href="https://reactjs.org/docs/portals.html"&gt;Portals&lt;/a&gt; in react.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Portals&lt;/strong&gt;?
&lt;/h2&gt;

&lt;p&gt;In our case we want to display our modal in the top of our DOM tree,but in the cases of nested modal the actual component might be linked to different DOM node, this can create problems and for this main reason we have Portals .&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What are Portals?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In React, portals can be used to render an element outside of its parent component’s DOM node while preserving its position in the React hierarchy, allowing it to maintain the properties and behaviors it inherited from the React tree.&lt;br&gt;
A typical use case for portals is when a parent component has an overflow: hidden or z-index style, but you need the child to visually “break out” of its container.&lt;br&gt;
So Portals are the best way to implement Modals for us. &lt;/p&gt;

&lt;p&gt;Enough of theory lets get to implementation.&lt;/p&gt;

&lt;p&gt;To implement the modal with Portals lets go in "index.html" file and add a dom root where we can render the portal. we are using id="modal-root" where we will render our Portal.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Code&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;noscript&amp;gt;&lt;/span&gt;You need to enable JavaScript to run this app.&lt;span class="nt"&gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"modal-root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we added the render root for the portal lets create a Modal component using Portal.&lt;/p&gt;

&lt;p&gt;As we are using reactstrap for displaying the modal, so the Modal tag takes two parameters ,a state variable "isOpen" of boolean type which tells the modal if it has to display or not, and a toggle function which is a function use for changing the state of the Modal.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Code&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;import React from "react";
import { Modal, ModalBody } from "reactstrap";
import ReactDOM from "react-dom";

const CreateCustomModal = (props) =&amp;gt; {
  if (props.isShowing) {
    return ReactDOM.createPortal(
      &lt;span class="nt"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Modal&lt;/span&gt;
          &lt;span class="na"&gt;isOpen=&lt;/span&gt;&lt;span class="s"&gt;{props.isShowing}&lt;/span&gt;
          &lt;span class="na"&gt;toggle=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; {
            props.setIsShowing(!props.isShowing);
          }}
        &amp;gt;
          &lt;span class="nt"&gt;&amp;lt;ModalBody&amp;gt;&lt;/span&gt;{props.children}&lt;span class="nt"&gt;&amp;lt;/ModalBody&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Modal&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;,
      document.querySelector("#modal-root")
    );
  } else return null;
};

export default CreateCustomModal;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as you can see in above code we created a portal and we are rendering it on different dom element i.e,"modal-root".&lt;/p&gt;

&lt;p&gt;For the final part we have to make a state variable which &lt;br&gt;
will handle the opening and closing of the modal. The point to be noted here is each component which wants to display the modal will contain their own state variable which handles the opening and closing of the modal, this way we will be able to handle the problem of opening another modal inside an open modal.&lt;/p&gt;

&lt;p&gt;Now to solve the first problem to display anything we want in a modal&lt;/p&gt;

&lt;p&gt;import the CreateCustomModal component in the component which wants to display modal.Create state variable "isshowing" and pass the variable and its callback to the CreateCustomModal component , enclose the content we want to display in modal between the opening and closing bracket of the CreateCustomModal.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Code&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;import CreateCustomModal from "./CreateCustomModal";
import React, { useState } from "react";

const DisplayModal =()=&amp;gt; {
  const [isShowing, setIsShowing] = useState(false);
  return (
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;I am outside the Modal&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;CreateCustomModal&lt;/span&gt; &lt;span class="na"&gt;isShowing=&lt;/span&gt;&lt;span class="s"&gt;{isShowing}&lt;/span&gt; &lt;span class="na"&gt;setIsShowing=&lt;/span&gt;&lt;span class="s"&gt;{setIsShowing}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        I am inside a Modal
      &lt;span class="nt"&gt;&amp;lt;/CreateCustomModal&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  );
}

export default DisplayModal;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We made a custom Modal component using React Portals and reactstrap&lt;/p&gt;

</description>
      <category>react</category>
      <category>modal</category>
      <category>reactportal</category>
    </item>
  </channel>
</rss>
