{"library":"react-reverse-portal","title":"React Reverse Portal","description":"React Reverse Portal is a utility library that enables the reparenting of rendered React elements within the DOM without triggering a re-render. Unlike standard React portals which allow an element rendered in one part of the React tree to be physically moved elsewhere in the DOM, reverse portals facilitate pulling an already rendered element from a source location into a target within the React tree. This mechanism is particularly useful for preserving internal React component state and inherent DOM element state (e.g., a playing video) when elements need to be moved, hidden, or reused across different parts of an application. The library is currently at version 2.3.0, actively maintained with a focus on stability and broad React version compatibility (16+). Key differentiators include its small bundle size, zero runtime dependencies, full TypeScript support, and the ability to define props at either the creation or usage location. It's designed for scenarios involving expensive-to-render components that benefit from being instantiated once and then dynamically placed or unplaced.","language":"javascript","status":"active","last_verified":"Sun Apr 19","install":{"commands":["npm install react-reverse-portal"],"cli":null},"imports":["import { createHtmlPortalNode } from 'react-reverse-portal';","import { InPortal } from 'react-reverse-portal';","import { OutPortal } from 'react-reverse-portal';"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import React from 'react';\nimport * as portals from 'react-reverse-portal';\n\n// A placeholder for an expensive component\nconst MyExpensiveComponent = ({ data }) => {\n  const [count, setCount] = React.useState(0);\n  React.useEffect(() => {\n    console.log(`MyExpensiveComponent rendered with data: ${data}`);\n  }, [data]);\n  return (\n    <div style={{ border: '1px solid gray', padding: '10px', margin: '10px' }}>\n      <h3>Expensive Component ({data})</h3>\n      <p>Internal state count: {count}</p>\n      <button onClick={() => setCount(c => c + 1)}>Increment</button>\n      <p>This component is rendered once and moved around.</p>\n    </div>\n  );\n};\n\nconst MyComponent = () => {\n  const portalNode = React.useMemo(() => portals.createHtmlPortalNode(), []);\n  const [showInFirstPlace, setShowInFirstPlace] = React.useState(true);\n\n  return (\n    <div>\n      <h1>React Reverse Portal Example</h1>\n\n      <div style={{ background: '#e0ffe0', padding: '15px', margin: '10px' }}>\n        <h2>Source Content (InPortal)</h2>\n        <p>This defines the content that will be moved:</p>\n        <portals.InPortal node={portalNode}>\n          <MyExpensiveComponent data=\"Source Data\" />\n        </portals.InPortal>\n        <p>The content above is rendered once but not necessarily visible here.</p>\n      </div>\n\n      <div style={{ background: '#ffe0e0', padding: '15px', margin: '10px' }}>\n        <h2>Destination 1 (OutPortal)</h2>\n        <button onClick={() => setShowInFirstPlace(true)}>\n          Show in Destination 1\n        </button>\n        {showInFirstPlace && (\n          <div style={{ border: '2px dashed blue', padding: '10px' }}>\n            <p>Content pulled here:</p>\n            <portals.OutPortal node={portalNode} />\n          </div>\n        )}\n      </div>\n\n      <div style={{ background: '#e0e0ff', padding: '15px', margin: '10px' }}>\n        <h2>Destination 2 (OutPortal)</h2>\n        <button onClick={() => setShowInFirstPlace(false)}>\n          Show in Destination 2\n        </button>\n        {!showInFirstPlace && (\n          <div style={{ border: '2px dashed green', padding: '10px' }}>\n            <p>Content pulled here:</p>\n            <portals.OutPortal node={portalNode} />\n          </div>\n        )}\n      </div>\n    </div>\n  );\n};\n\nexport default MyComponent;","lang":"typescript","description":"This quickstart demonstrates creating a stable portal node with `createHtmlPortalNode`, rendering an expensive component into it using `InPortal`, and then moving that same component between two different `OutPortal` locations in the DOM. The `MyExpensiveComponent` maintains its internal state and only renders once, showcasing the library's primary benefit of state preservation during DOM reparenting.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":null}