···11-<div align="center">
22- <img src="../../docs/assets/next-logo.png" alt="Next.js" height="200" width="200">
33- <img src="../../packages/site/src/assets/sidebar-badge.svg" alt="urql" height="200" width="200">
44- <br />
55- <a href="https://npmjs.com/package/next-urql">
66- <img alt="NPM Version" src="https://img.shields.io/npm/v/next-urql.svg" />
77- </a>
88-</div>
99-101## `next-urql`
112123A set of convenience utilities for using `urql` with Next.js.
1341414-### Motivation
1515-1616-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 `Promise`s. For more information, check out [`react-ssr-prepass`](https://github.com/FormidableLabs/react-ssr-prepass).
1717-1818-`next-urql` handles integrating this prepass step for you, such that your Next.js application using `urql` will prefetch your GraphQL queries on the server before sending down markup to the Client.
1919-2020-### Installation
2121-2222-Install `next-urql` along with its `peerDependencies`.
2323-2424-```sh
2525-yarn add next-urql react-is urql graphql
2626-# or
2727-npm install --save next-urql react-is urql graphql
2828-```
2929-3030-`react-is` helps to support server-side `Suspense` with `react-ssr-prepass`. This assumes you have followed the basic installation steps for `urql` [here](https://github.com/urql-graphql/urql#installation).
3131-3232-Note that if you are using Next before v9.4 you'll need to polyfill fetch, this can be
3333-done through [`isomorphic-unfetch`](https://www.npmjs.com/package/isomorphic-unfetch).
3434-3535-### Usage
3636-3737-To use `next-urql`, first `import` the `withUrqlClient` higher order component.
3838-3939-```javascript
4040-import { withUrqlClient } from 'next-urql';
4141-```
4242-4343-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:
4444-4545-```javascript
4646-import React from 'react';
4747-import Head from 'next/head';
4848-import { withUrqlClient } from 'next-urql';
4949-5050-import PokemonList from '../components/pokemon_list';
5151-import PokemonTypes from '../components/pokemon_types';
5252-5353-const Root = () => (
5454- <div>
5555- <Head>
5656- <title>Root</title>
5757- <link rel="icon" href="/static/favicon.ico" />
5858- </Head>
5959-6060- <PokemonList />
6161- <PokemonTypes />
6262- </div>
6363-);
6464-6565-export default withUrqlClient(() => ({ url: 'https://graphql-pokemon.now.sh' }))(Root);
6666-```
6767-6868-Read more below in the [API](#API) section to learn more about the arguments that can be passed to `withUrqlClient`.
6969-7070-#### Integration with `_app.js`
7171-7272-Next allows you to override the root of your application using a special page called [`_app.js`](https://nextjs.org/docs#custom-app). 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](https://nextjs.org/docs#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](#Caveats) section. Check out our example for using `next-urql` with `_app.js` [here](./examples/2-with-_app.js/README.md).
7373-7474-### API
7575-7676-`next-urql` exposes a single higher order component, `withUrqlClient`. This HoC accepts two arguments:
7777-7878-#### `clientOptions` (Required)
7979-8080-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:
8181-8282-```typescript
8383-type NextUrqlClientConfig = (ssrExchange: SSRExchange, ctx?: PartialNextContext) => ClientOptions;
8484-```
8585-8686-The `ClientOptions` `interface` comes from `urql` itself and has the following type:
8787-8888-```typescript
8989-interface ClientOptions {
9090- /** The GraphQL endpoint your application is using. */
9191- url: string;
9292- /** Any additional options to pass to fetch. */
9393- fetchOptions?: RequestInit | (() => RequestInit);
9494- /** An alternative fetch implementation. */
9595- fetch?: typeof fetch;
9696- /** The exchanges used by the Client. */
9797- exchanges?: Exchange[];
9898- /** A flag to enable suspense on the server. next-urql handles this for you. */
9999- suspense?: boolean;
100100- /** The default request policy for requests. */
101101- requestPolicy?: RequestPolicy;
102102- /** Use HTTP GET for queries. */
103103- preferGetMethod?: boolean;
104104- /** Mask __typename from results. */
105105- maskTypename?: boolean;
106106-}
107107-```
108108-109109-You can create a client by passing a function which receives the `ssrExchange` and Next's context object, `ctx`, as arguments 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. **Note: `ctx` is _only_ available on the initial server-side render and _not_ on client-side navigation**. This is necessary to allow for different Client configurations between server and client.
110110-111111-```typescript
112112-withUrqlClient((_ssrExchange, ctx) => ({
113113- url: 'http://localhost:3000',
114114- fetchOptions: {
115115- headers: {
116116- Authorization: ctx
117117- ? `Bearer ${ctx?.req?.headers?.Authorization ?? ''}`
118118- : localStorage.getItem('token') ?? '',
119119- },
120120- },
121121-}));
122122-```
123123-124124-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` set up for you, including the [`ssrExchange`](https://formidable.com/open-source/urql/docs/api/#ssrexchange-exchange-factory).
125125-126126-### Resetting the client instance
127127-128128-In rare scenario's you possibly will have to reset the client instance (reset all cache, ...), this is an uncommon scenario
129129-and we consider it "unsafe" so evaluate this carefully for yourself.
130130-131131-When this does seem like the appropriate solution any component wrapped with `withUrqlClient` will receive the `resetUrqlClient`
132132-property, when invoked this will create a new top-level client and reset all prior operations.
133133-134134-#### `exchanges`
135135-136136-When you're using `withUrqlClient` and you don't return an `exchanges` property we'll assume you wanted the default exchanges, these contain: `dedupExchange`, `cacheExchange`, `ssrExchange` (the one you received as a first argument) and the `fetchExchange`.
137137-138138-When you yourself want to pass exchanges don't forget to include the `ssrExchange` you received as the first argument.
139139-140140-#### `withUrqlClientOptions`
141141-142142-The second argument for `withUrqlClient` is an options object, this contains one `boolean` property named `ssr`, you can use this to tell
143143-`withUrqlClient` that the wrapped component does not use `getInitialProps` but the children of this wrapped component do. This opts you into
144144-`ssr` for these children.
145145-146146-### Different Client configurations on the client and the server
147147-148148-There are use cases where you may need different configurations for your `urql` Client on the client-side and the server-side; for example, you may want to interact with one GraphQL endpoint on the server-side and another on the client-side. `next-urql` supports this as of v0.3.0. We recommend using `typeof window === 'undefined'` or a `process.browser` check.
149149-150150-```typescript
151151-withUrqlClient({
152152- url:
153153- typeof window === 'undefined'
154154- ? 'https://my-server-graphql-api.com/graphql'
155155- : 'https://my-client-graphql-api.com/graphql',
156156-});
157157-```
158158-159159-If you want more customization of your Client instance to modify requests on specific routes, for instance, consider using a custom exchange. You can find an example of that [here](/examples/3-with-custom-exchange/README.md).
160160-161161-### Accessing the `urql` Client inside a Page component's `getInitialProps` method
162162-163163-There are use cases where you may want to access the `urql` Client instance inside your Page component's `getInitialProps` method. To support this, we actually attach the `urql` Client instance to the `ctx` object passed to your Page's `getInitialProps` method. You can access it like so:
164164-165165-```typescript
166166-import { NextUrqlPageContext } from 'next-urql';
167167-168168-const Page = () => {
169169- return <main />;
170170-};
171171-172172-Page.getInitialProps = async (ctx: NextUrqlPageContext) => {
173173- // Do something with the urql Client instance!
174174- let client = ctx.urqlClient;
175175-176176- return {
177177- ...props,
178178- };
179179-};
180180-```
181181-182182-### Usage with ReasonML
183183-184184-While there are no official bindings for using `next-urql` with ReasonML, porting `next-urql` to Reason is not too difficult. Moreover, having your own bindings means you can select only the pieces you need from the library. Here's an example of how you could bind `next-urql` if you only needed access to the non-functional `clientOptions` API, and only wanted to pass a `url` and `fetchOptions`. This assumes BuckleScript 7 to take advantage of records compiling into plain JS objects and assumes usage of [`bs-fetch`](https://github.com/reasonml-community/bs-fetch).
185185-186186-```reason
187187-type clientOptions = {
188188- url: string,
189189- fetchOptions: Fetch.requestInit
190190-};
191191-192192-[@bs.module "next-urql"]
193193-external withUrqlClient:
194194- (. clientOptions) =>
195195- (. React.component('props)) => React.component('props) =
196196- "withUrqlClient";
197197-```
198198-199199-Which can then be used like so:
200200-201201-```reason
202202-let headers = Fetch.HeadersInit.make({ "Content-Type": "application/json" });
203203-let client = {
204204- url: "https://mygraphqlapi.com/graphql",
205205- fetchOptions: Fetch.RequestInit.make(~headers, ~method_=POST, ())
206206-};
207207-208208-[@react.component]
209209-let make = () => {
210210- <h1>"Heck yeah, next-urql with Reason!"->React.string</h1>
211211-};
212212-213213-let default = (withUrqlClient(. clientOptions))(. make);
214214-```
215215-216216-The great part about writing thin bindings like this is that they are zero cost – in fact, the above bindings get totally compiled away by BuckleScript, so you get the full benefits of type safety with absolutely zero runtime cost!
217217-218218-### Restricting Data Fetching to the Server
219219-220220-If you want to use a `Client` in Next.js' newer methods like `getServerSideProps` you may use the `initUrqlClient` function to create a client on the fly. This will need to be done per request.
221221-222222-```javascript
223223-import { initUrqlClient } from 'next-urql';
224224-225225-export const getServerSideProps = async ctx => {
226226- const client = initUrqlClient(
227227- {
228228- url: '/graphql',
229229- },
230230- false /* set to false to disable suspense */
231231- );
232232-233233- const result = await client.query(QUERY, {}).toPromise();
234234-235235- return {
236236- props: { data: result.data },
237237- };
238238-};
239239-```
240240-241241-The first argument passed to the `initUrqlClient` function is the same object that we'd normally pass to `createClient`.
242242-The second argument is a `boolean` flag indicating whether or not to enable `suspense`; typically, we'd disable it for manual usage.
243243-244244-### Examples
245245-246246-You can see simple example projects using `next-urql` in the `examples` directory or on [CodeSandbox](https://codesandbox.io/s/next-urql-pokedex-oqj3x).
247247-248248-### Caveats
249249-250250-Using `withUrqlClient` on a page that has `getInitialProps` will opt that component and it's children into a prepass that does a first pass of all queries, when that
251251-component has children using `getInitialProps` but that component itself is not and you want to opt in to this behavior you'll have to set the second argument of
252252-`withUrqlClient`, this means `withUrqlClient(() => clientOptions, { ssr:true })`.
253253-This measure is available so we can support `getStaticProps`, ...
254254-255255-When you are using `getStaticProps`, `getServerSideProps`, or `getStaticPaths`, you should opt-out of `Suspense` by setting the `neverSuspend` option to `true` in your `withUrqlClient` configuration.
256256-your `withUrqlClient`.
257257-During the prepass of your component tree `next-urql` can't know how these functions will alter the props passed to your page component. This injection
258258-could change the `variables` used in your `useQuery`. This will lead to error being thrown during the subsequent `toString` pass, which isn't supported in React 16.
55+More documentation is available at https://urql.dev/goto/docs/advanced/server-side-rendering/#nextjs
66+Examples can be found at https://github.com/urql-graphql/urql/tree/main/examples/with-next