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

react-portal-target

v1.0.2

Published

React portals which target another location in the React component tree

Downloads

264

Readme

React Portal Target

Allows React components to put content elsewhere on the page, for example pages defining content to show in a shared header or footer.

Like React Portal, but the target is another location in the React component tree (or a hook) instead of targeting a DOM node.

Example

npm install --save react-portal-target

Components API

const MyHeader = () => (
  <header>Welcome. <PortalTarget name="mytarget" /></header>
);

const MyPage = () => (
  <main>
    This is a page
    <PortalSource name="mytarget">
      You're looking at page <strong>one</strong>
    </PortalSource>
  </main>
);

ReactDOM.render((
  <PortalContext>
    <MyHeader />
    <MyPage />
  </PortalContext>
), document.body);

Renders as:

<header>Welcome. You're looking at page <strong>one</strong></header>
<main>This is a page</main>

Hooks API

Note that the components API simply wraps the hooks, and is recommended in most cases. But if you need to be able to perform additional processing, you can use the hooks directly (it is also possible to mix-and-match the hooks and components APIs, for example using a hook target and a component source).

const MyHeader = () => {
  const content = usePortalTarget('mytarget');
  if (!content) {
    return (<header>No page active!</header>);
  }
  return (<header>Welcome. {content}</header>);
};

const MyPage = () => {
  usePortalSource(
    'mytarget',
    <>You're looking at page <strong>one</strong></>
  );
  return (<main>This is a page</main>);
};

ReactDOM.render((
  <PortalContext>
    <MyHeader />
    <MyPage />
  </PortalContext>
), document.body);

Renders as:

<header>Welcome. You're looking at page <strong>one</strong></header>
<main>This is a page</main>

API

<PortalContext>

<PortalContext>...</PortalContext>

Provides the context for passing data between components. This should be high up in your component tree so that it contains all sources and targets.

If not used, a global context is used by default.

<PortalTarget>

<PortalTarget name="my-target-name" />
<PortalTarget name="my-target-name">default content</PortalTarget>

Defines an outlet for displaying content. You can optionally specify default content to display when no sources are linked to the target.

The content will be wrapped in a React Fragment.

If multiple targets are defined with the same name, the content will only be shown in the first target to render (once that target unmounts, it will move to the second, and so on.)

See also usePortalTarget.

usePortalTarget

content = usePortalTarget(name)
content = usePortalTarget(name, defaultContent)

Defines an outlet for displaying content, returning the current content. You can optionally specify default content to return when no sources are linked to the target.

The content is returned exactly as it was provided, with no processing or wrapping.

See also PortalTarget.

<PortalSource>

<PortalSource name="my-target-name">content</PortalSource>

Defines an inlet for providing content.

If multiple sources are defined for the same target, only one will be displayed at a time (the first to render, though this may not always be the first on the page).

See also usePortalSource.

usePortalSource

usePortalSource(name, content)

Defines an inlet for providing content. The content should be one of:

  • a string,
  • an element,
  • null
  • an array of the above

The recommended way to provide multi-element content is to wrap it in a fragment:

usePortalSource('my-thing', <>foo<strong>bar</strong></>);

but it is also possible to provide it as an array:

usePortalSource('my-thing', ['foo', <strong>bar</strong>]);

See also PortalSource.

Caveats

Because this internally relies on useLayoutEffect, it will not render as part of server-side-rendering (the portaled content will be unavailable until the tree is hydrated on the client). If server-side-rendering is important to you, you will need to re-structure your page to put the portaled content directly inside the target element.