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 🙏

© 2024 – Pkg Stats / Ryan Hefner

promise-portal-react

v0.1.38

Published

Allow rendering of promise based components in react and react-native

Downloads

5,044

Readme

Tests Codacy Badge codecov npm version

Modals in React are difficult for a couple main reasons. (1) They require a lot of boilerplate to set up, and (2) they are typically "fire and forget", so the caller cannot know what was the result of the user's interaction with the modal. PromisePortal solves these problems, and more.

Installation

For npm:

npm i promise-portal-react

For yarn:

yarn add promise-portal-react

Getting Started

First off, you need to mount the portal provider somewhere in the application. Ideally, it should be close to the root, but below any configuration components like context providers, global error boundaries, etc.

import PromisePortal from "promise-portal-react";
// ...
  return (
    <View>
      <PromisePortal.Provider>
        // ...
      </PromisePortal.Provider>
    </View>
  );
// ...

Any components that you show through promise-portal will be mounted here in the view tree.

Usage

Now, to show a component using the usePromisePortal hook:

import { usePromisePortal } from "react-promise-portal";
import SomeModal from "./SomeModal";

function MyComponent(props) {
  const { showPortalAsync } = usePromisePortal();
  const onButtonPress = async () => {
    const result = await showPortalAsync(SomeModal);
  }

  return (
    <Button onPress={onButtonPress}>
      Press me!
    </Button>
  );
}

export default MyComponent;

or using class-based components via the withPromisePortal HOC:

import { withPromisePortal } from "promise-portal-react";

class MyComponent extends React.Component {
  onButtonPress = async () => {
    const result = await this.props.showPortalAsync(SomeModal);
  }

  render() {
    <Button onPress={this.onButtonPress}>
      Press me!
    </Button>
  }
}

export default withPromisePortal(MyComponent);

And you now you can render a component near the root of the application from anywhere, and the caller knows what the result of the user interaction was!

So how does the caller get the result back? When a component is shown via the promise-portal it injects two props: (1) complete and (2) cancel. These can be though of as resolve and reject. complete(data) will resolve the promise-component returning the data payload in the result that will be received by the caller. cancel() will reject the promise-component and cancelled will be true in the result.

Portal component

Sometimes you don't want to call to show the component imperatively. Sometimes you just want to want to render the component just like any other component, but have it mount at a different part of the component tree. You can do that as well:

import { Portal } from "promise-portal-react";

function MyComponent() {
  return (
    <Portal>
      <SomeModal />
    </Portal>
  );
}

| Prop | Type | Description | Default | |---|---|---|---| | closeStrategy | 'cancel', 'requestClose' | The method to use when closing the portal. cancel will clear the portal immediately, requestClose toggles the component's open prop for orchestrating close transistions. | 'cancel' |

Why use promise portal?

Frequently we just want to pop up a dialog or modal to get feedback from the user. Traditional modals in React require quite a bit of boilerplate, and in many scenarios it is difficult to get the result of the user interaction back to the caller. You can think of promise portals as an asynchronous method for getting user input. Of course you can use it as a simplified API for presenting modals as well.

Caveats

Since promise-components are being rendered via a promise, the in-going props cannot be updated. In many cases this is acceptable, or even desired behavior, but it is important to be aware of. Components being shown can still manage their own data dependencies internally, but the caller cannot pass down new props. At some point this feature may be added, but I haven't found any use for it yet.

When my button is tapped twice rapidly it shows multiple portals

This is because each button press dispatches a separate portal. There are a few ways to address this. Of course you could track some state to know if the modal is open, but that was one of the things we were trying to avoid. You could also add a debounce to the button press handler to prevent users from mashing the button. Lastly, simply provide a key prop to when showing the portal. Portals attempting to be shown while another portal with a duplicate key are ignored.