Giter Site home page Giter Site logo

next-urql's Introduction

next-urql

A set of convenience utilities for using urql with NextJS.

Motivation

Using GraphQL with server-side rendering in React is a challenging problem. Currently, React has no support for Suspense for data fetching on the server. To get around this, a prepass step can be used to walk the tree (or a subsection of the tree) of your React application and suspend when it encounters thrown Promises. For more information, check out react-ssr-prepass.

next-urql handles integrating this prepass step for you, such that your NextJS application using urql will prefetch your GraphQL queries on the server before sending down markup to the client.

Installation

Install next-urql along with its peerDependencies.

npm install --save next-urql react-is styled-components isomorphic-unfetch

react-is, styled-components, and isomorphic-unfetch help to support server-side Suspense with react-ssr-prepass. This assumes you have followed the basic installation steps for urql here.

Usage

To use next-urql, first import the withUrqlClient higher order component.

import { withUrqlClient } from 'next-urql';

Then, for any page in your pages directory for which you want to prefetch GraphQL queries, wrap the page in withUrqlClient. For example, let's say you have an index.js page that renders two components that make GraphQL requests using urql, PokemonList and PokemonTypes. To run their queries initially on the server-side you'd do something like the following:

import React from 'react';
import Head from 'next/head';
import { withUrqlClient } from 'next-urql';

import PokemonList from '../components/pokemon_list';
import PokemonTypes from '../components/pokemon_types';

const Root = () => (
  <div>
    <Head>
      <title>Root</title>
      <link rel="icon" href="/static/favicon.ico" />
    </Head>

    <PokemonList />
    <PokemonTypes />
  </div>
);

export default withUrqlClient({ url: 'https://graphql-pokemon.now.sh' })(Root);

Read more below in the API section to learn more about the arguments that can be passed to withUrqlClient.

Integration with _app.js

Next allows you to override the root of your application using a special page called _app.js. If you want to have all GraphQL requests in your application fetched on the server-side, you could wrap the component exported by _app.js in withUrqlClient. However, be aware that this will opt you out of automatic static optimization for your entire application. In general, it's recommended practice to only use withUrqlClient on the pages that have GraphQL operations in their component tree. Read more in the Caveats section.

API

next-urql exposes a single higher order component, withUrqlClient. This HoC accepts two arguments:

clientOptions (Required)

The clientOptions argument is required. It represents all of the options you want to enable on your urql Client instance. It has the following union type:

type NextUrqlClientOptions =
  | Omit<ClientOptions, 'exchanges' | 'suspense'>
  | ((
      ctx: NextContext<any, any>,
    ) => Omit<ClientOptions, 'exchanges' | 'suspense'>);

The ClientOptions interface comes from urql itself and has the following type:

interface ClientOptions {
  /** The GraphQL endpoint your application is using. */
  url: string;
  /** Any additional options to pass to fetch. */
  fetchOptions?: RequestInit | (() => RequestInit);
  /** An alternative fetch implementation. */
  fetch?: typeof fetch;
  /** The default request policy for requests. */
  requestPolicy?: RequestPolicy;
}

This means you have two options for creating your urql Client. The first involves just passing the options as an object directly:

withUrqlClient({
  url: 'http://localhost:3000',
  fetchOptions: {
    referrer: 'no-referrer',
    redirect: 'follow',
  },
});

The second involves passing a function, which receives Next's context object, ctx, as an argument and returns urql's client options. This is helpful if you need to access some part of Next's context to instantiate your client options:

withUrqlClient(ctx => ({
  url: 'http://localhost:3000',
  fetchOptions: {
    headers: {
      Authorization: `Bearer ${ctx.req.headers.token}`,
    },
  },
}));

In client-side SPAs using urql, you typically configure the Client yourself and pass it as the value prop to urql's context Provider. withUrqlClient handles setting all of this up for you under the hood. By default, you'll be opted into server-side Suspense and have the necessary exchanges setup for you, including the ssrExchange. If you need to customize your exchanges beyond the defaults next-urql provides, use the second argument to withUrqlClient, mergeExchanges.

mergeExchanges (Optional)

The mergeExchanges argument is optional. This is a function that takes the ssrExchange created by next-urql as its only argument and allows you to configure your exchanges as you wish. It has the following type signature:

(ssrExchange: SSRExchange) => Exchange[]

By default, next-urql will incorprate the ssrExchange into your exchanges array in the correct location (after any other caching exchanges, but before the fetchExchange โ€“ read more here). Use this argument if you want to configure your client with additional custom exchanges, or access the ssrCache directly to extract or restore data from its cache.

Example

You can see an example project with next-urql in our example directory or on CodeSandbox.

Caveats

withUrqlClient implements NextJS's unique getInitialProps method uner the hood. This means that any page containing a component wrapped by withUrqlClient will be opted out of automatic static optimization. Automatic static optimization was added in Next v9, so you shouldn't worry about this if using an earlier version of Next. This is not unique to next-urql โ€“ any implementation of getInitialProps by any component in your application will cause Next to opt out of automatic static optimization.

next-urql's People

Contributors

kylealwyn avatar parkerziegler avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.