react-waterfall-render

Renders nested React components with asynchronous cached loading; useful for GraphQL clients and server side rendering.

Usage no npm install needed!

<script type="module">
  import reactWaterfallRender from 'https://cdn.skypack.dev/react-waterfall-render';
</script>

README

react-waterfall-render

npm version CI status

Renders nested React components with asynchronous cached loading.

Useful for GraphQL clients (e.g. graphql-react) and server side rendering.

Installation

To install with npm, run:

npm install react-waterfall-render

Use the WaterfallRenderContext in React components to declare asynchronous cached loading, and use the function waterfallRender to server side render your React app in a fully loaded state.

Requirements

  • Node.js: ^12.22.0 || ^14.17.0 || >= 16.0.0
  • Browsers: > 0.5%, not OperaMini all, not IE > 0, not dead

Exports

These ECMAScript modules are published to npm and exported via the package.json exports field:

waterfallRender.mjs

Export default

Function waterfallRender — Resolves a React node rendered with all data loaded within cached; typically a HTML string.

It repeatedly renders the React node and awaits any loading cache promises declared within (using the declare loading function via WaterfallRenderContext, until no further loading is declared; implying all data has loaded and is rendered from cache.

If server side rendering, afterwards the cache should be serialized for hydration on the client prior to the initial client side render.

Intended for use in a server environment environment for server side rendering, but could potentially be used for preloading components in modern browser environments that support async functions, etc.

Parameters
  1. reactNode: React.ReactNode — React node to render.
  2. render: Function — Synchronous React render function, e.g. ReactDOMServer.renderToStaticMarkup (faster), or ReactDOMServer.renderToString (slower).
Returns

Promise<unknown> — Resolves the final render result, typically a HTML string.

Type DeclareLoading

Function — Declares loading cache promises to waterfallRender. Available within React components via WaterfallRenderContext.

Parameters
  1. ...promises: Promise<any> — Promises that resolve once loading data has been cached. The values resolved don’t matter. Multiple arguments can be used, similar to how Array.push works.
Returns

void

Example 1

Loading data in a React component within a server and client side rendered app.

import React from "react";
import WaterfallRenderContext from "react-waterfall-render/WaterfallRenderContext.mjs";
import useUserProfileData from "../hooks/useUserProfileData.mjs";
import UserProfile from "./UserProfile.mjs";

export default function UserPage({ userId }) {
  const declareLoading = React.useContext(WaterfallRenderContext);
  const { load, loading, cache } = useUserProfileData(userId);

  // For this example, assume loading errors are cached.
  if (cache) return <UserProfile data={cache} />;

  if (!loading) {
    const userDataPromise = load();

    // Only present when the app is server side rendered using the function
    // `waterfallRender`.
    if (declareLoading) {
      declareLoading(userDataPromise);

      // This render is on the server and will be discarded anyway for a
      // re-render once the declared loading promises resolve, so it’s
      // slightly more efficient to render nothing; particularly if the
      // loading state is expensive to render.
      return null;
    }
  }

  return "Loading…";
}

WaterfallRenderContext.mjs

Export default

React.Context<DeclareLoading | undefined> — The WaterfallRenderContext React context for making the declare loading function available within components when rendering with waterfallRender.

Example 1

Use within a component with the React hook useContext.

import React from "react";
import WaterfallRenderContext from "react-waterfall-render/WaterfallRenderContext.mjs";
const declareLoading = React.useContext(WaterfallRenderContext);