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

@urql/exchange-suspense

v1.9.2

Published

An exchange for client-side React Suspense support in urql

Downloads

583

Readme

@urql/exchange-suspense is an exchange for the urql GraphQL client that allows the use of React Suspense on the client-side with urql's built-in suspense mode.

urql already supports suspense today, but it's typically used to implement prefetching during server-side rendering with react-ssr-prepass, which allows it to execute React suspense on the server. But since <Suspense> is mainly intended for client-side use it made sense to build and publish this exchange, which allows you to try out urql and suspense in your React app!

⚠️ *Deprecated: This package is deprecated! Usage of client-side suspense with urql isn't recommended anymore and this packages has been marked as deprecated after being experimental, since all it allows for is to use Suspense as a fancier loading boundary, which isn't its intended use. This exchange may still be useful when used with care, but it's worth keeping in mind that the suspense patterns in urql for the client-side may change. Suspense-mode usage for SSR remains unchanged and undeprecated however.

Quick Start Guide

First install @urql/exchange-suspense alongside urql:

yarn add @urql/exchange-suspense
# or
npm install --save @urql/exchange-suspense

You'll then need to add the suspenseExchange, that this package exposes, to your urql Client and set the suspense mode to true:

import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
import { suspenseExchange } from '@urql/exchange-suspense';

const client = createClient({
  url: 'http://localhost:1234/graphql',
  suspense: true, // Enable suspense mode
  exchanges: [
    dedupExchange,
    suspenseExchange, // Add suspenseExchange to your urql exchanges
    cacheExchange,
    fetchExchange,
  ],
});

Important: In React Suspense when a piece of data is still loading, a promise will be thrown that tells React to wait for this promise to complete and try rendering the suspended component again. The suspenseExchange works by caching the result of any operation until React retries, but it doesn't replace the cacheExchange, since it only briefly keeps the result around.

This means that, in your array of Exchanges, the suspenseExchange should be added after the dedupExchange and before the cacheExchange.

Usage

After installing @urql/exchange-suspense and adding it to your urql client, urql will load all your queries in suspense mode. So instead of relying on the fetching flag, you can wrap your components in a <Suspense> element.

import React from 'react';
import { useQuery } from 'urql';

const LoadingIndicator = () => <h1>Loading...</h1>;

const YourContent = () => {
  const [result] = useQuery({ query: allPostsQuery });
  // result.fetching will always be false here, as
  // this component only renders when it has data
  return null; // ...
};

<React.Suspense fallback={<LoadingIndicator />}>
  <YourContent />
</React.Suspense>;

Note that in React Suspense, the thrown promises bubble up the component tree until the first React.Suspense boundary. This means that the Suspense boundary does not need to be the immediate parent of the component that does the fetching! You should place it in the component hierarchy wherever you want to see the fallback loading indicator, e.g.

<React.Suspense fallback={<LoadingIndicator />}>
  <AnyOtherComponent>
    <AsDeepAsYouWant>
      <YourContent />
    </AsDeepAsYouWant>
  </AnyOtherComponent>
</React.Suspense>

You can also find a fully working demo on CodeSandbox.

Caveats

About server-side usage

The suspense exchange is not intended to work for server-side rendering suspense! This is what the ssrExchange is intended for and it's built into the main urql package. The suspenseExchange however is just intended for client-side suspense and use with <React.Suspense>.

The <React.Suspense> element currently won't even be rendered during server-side rendering, and has been disabled in react-dom/server. So if you use suspenseExchange and <React.Suspense> in your server-side code you may see some unexpected behaviour and errors.

Usage with ssrExchange

If you're also using the ssrExchange for server-side rendered data, you will have to use an additional flag to indicate to it when it's running on the server-side and when it's running on the client-side.

By default, the ssrExchange will look at client.suspense. If the urql Client is in suspense mode then the ssrExchange assumes that it's running on the server-side. When it's not in suspense mode (!client.suspense) it assumes that it's running on the client-side.

When you're using @urql/exchange-suspense you'll enable the suspense mode on the client-side as well, which means that you'll have to tell the ssrExchange manually when it's running on the client-side.

Most of the time you can achieve this by checking process.browser in any Webpack environment. The ssrExchange accepts an isClient flag that you can set to true on the client-side.

const isClient = !!process.browser;

const client = createClient({
  url: 'http://localhost:1234/graphql',
  suspense: true,
  exchanges: [
    dedupExchange,
    isClient && suspenseExchange,
    ssrExchange({
      initialData: isClient ? window.URQL_DATA : undefined,
      // This will need to be passed explicitly to ssrExchange:
      isClient: !!isClient
    })
    cacheExchange,
    fetchExchange,
  ].filter(Boolean),
});