Library / SDK
cloudflare/react-gateway avatar
cloudflare/react-gateway

react-gateway renders React trees into a named destination

Render React DOM into a new context (aka "Portal")

576 stars70 forksJavaScriptBSD-3-Clause

At a glance

What is it?
react-gateway is a Cloudflare library that renders part of a React tree into another part of the tree through a named gateway and destination, and unlike a DOM portal it works in server-side rendered and React Native applications. It suits a modal or dialog that has to survive universal rendering, and it needs a provider at the root.
Who is it for?
Adopt react-gateway when you need a modal or overlay that renders into a different part of the document and you also do server-side rendering, since a DOM portal is awkward in that setting. Do not adopt it if your application only runs in the browser, since a portal is simpler there, and note that the package manifest still targets React 15 era tooling.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What a gateway is, in one sentence

The library's own description is the shortest possible statement of the idea. React Gateway renders React DOM into a new context, also called a Portal, and it can be used to implement various UI components such as modals. The reference implementation is react-modal2, another Cloudflare project, and the fact that the README names it is the fastest way to see the intended use case. A modal is the classic case where a component needs to appear somewhere other than where it is written, because the visual placement has to be fixed to the top of the document while the component that triggers it lives deep in the tree, and the two must share React context. What a gateway gives you is a named channel between the two places, so the source can say render into global and the destination can say I am global, without either knowing about the other.

The three components and how they fit

The example in the README is small enough to read in full and it shows the whole API. You import Gateway, GatewayDest and GatewayProvider, wrap the application in a GatewayProvider, and then use Gateway with an into prop to name a destination and GatewayDest with a name prop to place the receiving end. The rendered result is shown as well, and it is worth reading because it shows what the library actually does to the tree. The two Gateway children are lifted out of where they were written and appear under the corresponding GatewayDest elements, and in the rendered output the container div holds a noscript element in place of each lifted child, the third item that was not lifted stays where it was, and the two destinations render as a section with the hello class and a plain div. So the source position leaves a placeholder and the destination holds the real content, which is the mechanism a modal needs and is also how the library keeps server-side rendering consistent.

Why it is not a DOM portal

The How it works section states the design decision and the reason for it. React Gateway works very differently than most React portals in order to work in server-side rendered React applications. It maintains an internal registry of containers and children which manages where things should be rendered. That registry is created by the GatewayProvider and passed to the Gateway and GatewayDest components invisibly via React's contextTypes. Whenever a child or container is added or removed, React Gateway will update its internal registry and ensure things are properly rendered. The difference from a portal is that a portal reaches into the DOM directly, and the DOM does not exist on the server in the same shape, so a portal-rendered subtree cannot be serialised into the server-rendered HTML in the right place. A registry of named containers solves that, because the mapping from source to destination is data rather than a DOM operation, so the server can produce the same output the client would. The cost is that you have to remember to put the provider high enough in the tree, and that the destination has to exist in the same render pass.

Putting it in your application, step by step

The usage section walks through the three edits, and each is shown as a diff, which is the clearest possible way to present a change to a component tree. First you wrap the application in the provider:

diff
  import React from 'react';
+ import {
+   GatewayProvider
+ } from 'react-gateway';

  export default class Application extends React.Component {
    render() {
      return (
+       <GatewayProvider>
          <div>
            {this.props.children}
          </div>
+       </GatewayProvider>
      );
    }
  }

Then you insert a destination wherever you want the content to appear, giving it a name, and then in any component rendered inside the provider you add a Gateway with the matching into prop. If you want to customise the destination element you can pass any props to GatewayDest, including component, which allows you to specify a tagName or custom component, and they are passed to the created element.

React Native needs a different component for the destination

React Gateway does not directly depend on react-dom, so it works fine with React Native under one condition, and the README states it in bold because it is the one thing that will bite you. You must pass a React Native component like View or similar to the component prop of the destination. Because if you do not, the destination will try to render a div element, which is not available. The Native example makes this concrete, with the destination rendered as GatewayDest name one component View, and the surrounding tree using View and Text from react-native. The fact that the library does not depend on react-dom is what makes this possible at all, since a portal implementation would have to reach into react-dom to create its container. A React Native destination is a view, and the same registry mechanism serves both platforms.

The package targets an older React and an older toolchain

The package manifest is where you find the caveats. The version in the manifest is 3.0.0 and the main entry is lib/index.js, with the build script running babel src -d lib. The runtime dependencies are only prop-types and react-prop-types, which is the whole reason the library can work without react-dom, and the peer dependency range is react 0.14.0 or 15.0.0 or 16.0.0. So the supported React range stops at 16, and it does not cover React 17 or newer, and if you are on a current React you should expect to be outside what this package was tested against. The dev dependencies tell the same story, with react and react-dom at 15.0.0-0, babel-cli and babel-core at 6.x, karma 0.13, mocha 2.3, chai 3.4, eslint 1.8 and jsfmt for formatting, and the test script is karma start with a karma.conf.js at the root. The repository also has an example/ directory with Application.js, browser.js, server.js and styles.css, and the example script bundles the browser entry with browserify and runs the server with babel-node, which is the universal example the README refers to.

Editorial conclusion

Adopt react-gateway when you need a modal or overlay that renders into a different part of the document and you also do server-side rendering, since a DOM portal is awkward in that setting. Do not adopt it if your application only runs in the browser, since a portal is simpler there, and note that the package manifest still targets React 15 era tooling. Verify first that the version of React you use is inside the peer dependency range of 0.14, 15 or 16, that you pass a component prop to the destination when running under React Native, and that the provider wraps every component that renders a gateway.

Frequently asked questions

What does react-gateway do?

It renders React DOM into a new context, also called a Portal. You mark a subtree with a Gateway and an into name, and place a GatewayDest with a matching name where the content should appear, which is how you implement components such as modals.

How is react-gateway different from a React portal?

It works very differently than most React portals in order to work in server-side rendered React applications. It maintains an internal registry of containers and children, created by the GatewayProvider and passed down through React's contextTypes, and updates that registry whenever a child or container is added or removed, so the mapping is data rather than a DOM operation.

How do I use react-gateway in React Native?

The library does not depend on react-dom so it works, under one condition: you must pass a React Native component like View to the component prop of the GatewayDest. Otherwise it tries to render a div element, which is not available on that platform.

Which React versions does react-gateway support?

The peer dependency range is react 0.14.0 or 15.0.0 or 16.0.0, and the dev dependencies pin react and react-dom at 15.0.0-0. The runtime dependencies are only prop-types and react-prop-types, which is what lets the library work without react-dom.

Official sources

  1. cloudflare/react-gateway on GitHub
  2. Issues
  3. License: BSD-3-Clause
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cloudflare-react-gateway.svg)](https://hysenlabs.com/projects/cloudflare-react-gateway)

Was this useful?