npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

use-imperative-portal

v1.0.8

Published

0.6kB portals for React. Open anywhere

Readme

use-imperative-portal 🔮

version minzip size license

Manage React portals imperatively with minimal overhead. A single function call lets you open, update, and close portals.

Features ✨

  • 🚀 Tiny (0.6kB gzipped) with no external dependencies
  • 🧩 Imperative API for opening, updating, and closing
  • 🔎 Lifecycle awareness through isClosed property
  • 🌐 Supports React DOM and React Native
  • 🔀 Multiple isolated contexts (useful for modals, toasts, etc.)
  • 💻 Includes TypeScript definitions

Installation

npm install use-imperative-portal

Quick Start

import { openPortal, PortalEndpoint } from 'use-imperative-portal'

// Render endpoint once at root level
ReactDOM.createRoot(document.getElementById('root')).render(
    <>
        <App />
        <PortalEndpoint /> {/* Portals render here */}
    </>
)

function PaymentButton() {
    const handlePay = async () => {
        // Open portal with initial content
        const portal = openPortal(<div>Processing payment...</div>)

        try {
            await processPayment()
            // Update portal content
            portal.update(<div>Payment complete!</div>)
        } catch (error) {
            // Update with error state
            portal.update(<div className="error">Payment failed!</div>)
        } finally {
            // Close after 2 seconds
            setTimeout(portal.close, 2000)
        }
    }

    return <button onClick={handlePay}>Pay Now</button>
}

Advanced Recipes

Global Error Handler (Non-component)

// api.js
import { openPortal } from 'use-imperative-portal'

export const apiClient = {
    async get(url) {
        try {
            return await axios.get(url)
        } catch (error) {
            const portal = openPortal(() => {
                //  Access portal object in render function
                return <Toast message="API Error!" onClose={portal.close} />
            })
            throw error
        }
    },
}

Dynamic Content Update

Pass a function to create updatable portals:

function ProgressTracker() {
    const startUpload = () => {
        // Create portal with dynamic content function
        const portal = openPortal((percent = 0, status = 'Preparing') => (
            <div>
                <ProgressBar value={percent} />
                <span>{status}</span>
            </div>
        ))

        simulateUpload({
            onProgress: pct => {
                portal.update(pct, 'Uploading...')
            },
            onComplete: () => {
                portal.update(100, 'Processing')
                setTimeout(portal.close, 1000)
            },
        })
    }

    return <button onClick={startUpload}>Start Upload</button>
}

Multi-context Isolation

Create separate portal environments for different use cases:

const ModalContext = createPortalContext()
const NotificationContext = createPortalContext()

function Root() {
    return (
        <>
            <NotificationContext.Endpoint />
            <main>
                <App />
            </main>
            <ModalContext.Endpoint />
        </>
    )
}

function App() {
    const showModal = () => ModalContext.openPortal(<Dialog />)
    const notify = () => NotificationContext.openPortal(<Toast />)

    return (
        <>
            <button onClick={showModal}>Open Dialog</button>
            <button onClick={notify}>Show Toast</button>
        </>
    )
}

API Reference ⭐

openPortal(node)

Opens a new portal and returns a controller object to manage it.

  • Parameters:

    • node: A React node (like JSX elements, strings, numbers) or a function that returns a React node.
      • When providing a function:
        • Must accept zero arguments initially (parameters should be optional)
        • Will be called immediately without arguments when opening the portal
        • Parameters can be passed later via portal.update()
  • Returns an object with:

    • update(...args): Updates the portal's content.
      • If node was a function, pass the same arguments expected by that function
      • If node was a static React node, pass a single argument with the new React node
    • close(): Closes the portal and removes it from the endpoint
    • isClosed: A boolean (read-only) that becomes true once the portal is closed

PortalEndpoint

A React component that renders all active portals. Include this component once in your app's root or wherever portals should appear.

function App() {
    return (
        <div>
            <MainContent />
            <PortalEndpoint /> {/* Portals render here */}
        </div>
    )
}

createPortalContext()

Creates an independent portal environment for isolated groups (e.g., separate modal and notification systems).

  • Returns an object containing:
    • openPortal: Function identical to the default openPortal, but scoped to this context.
    • Endpoint: Component where portals from this context will render.
// Create separate contexts
const ModalContext = createPortalContext()
const ToastContext = createPortalContext()

function App() {
    return (
        <>
            <ModalContext.Endpoint /> {/* Modals render here */}
            <ToastContext.Endpoint /> {/* Toasts render here */}
            <MainApp />
        </>
    )
}

function openModal() {
    ModalContext.openPortal(<Dialog />) // Opens in ModalContext's endpoint
}

Why This Library? 🏆

Traditional portal solutions often:

  • Require complex component hierarchies
  • Lack clear lifecycle management
  • Offer a single portal destination
  • Include heavier dependencies

use-imperative-portal tackles these by:

  • ✨ Allowing direct imperative control
  • 🔎 Exposing lifecycle awareness via isClosed
  • 🏝️ Supporting isolated contexts for different use cases
  • 📦 Keeping footprint small and usage simple

License

MIT © skt-t1-byungi