diff --git a/examples/with-graphql-hooks/.nowignore b/examples/with-graphql-hooks/.nowignore
new file mode 100644
index 0000000000000..b512c09d47662
--- /dev/null
+++ b/examples/with-graphql-hooks/.nowignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
diff --git a/examples/with-graphql-hooks/README.md b/examples/with-graphql-hooks/README.md
new file mode 100644
index 0000000000000..6380cd3013d2e
--- /dev/null
+++ b/examples/with-graphql-hooks/README.md
@@ -0,0 +1,52 @@
+[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-graphql-hooks)
+
+# GraphQL Hooks Example
+
+This started life as a copy of the `with-apollo` example. We then stripped out Apollo and replaced it with `graphql-hooks`. This was mostly as an exercise in ensuring basic functionality could be achieved in a similar way to Apollo. The [bundle size](https://bundlephobia.com/result?p=graphql-hooks@3.2.1) of `graphql-hooks` is tiny in comparison to Apollo and should cover a fair amount of use cases.
+
+## Demo
+
+https://next-with-graphql-hooks.now.sh
+
+## How to use
+
+### Using `create-next-app`
+
+Execute [`create-next-app`](https://github.com/segmentio/create-next-app) with [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) or [npx](https://github.com/zkat/npx#readme) to bootstrap the example:
+
+```bash
+npx create-next-app --example with-graphql-hooks with-graphql-hooks-app
+# or
+yarn create next-app --example with-graphql-hooks with-graphql-hooks-app
+```
+
+### Download manually
+
+Download the example:
+
+```bash
+curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-graphql-hooks
+cd with-graphql-hooks
+```
+
+Install it and run:
+
+```bash
+npm install
+npm run dev
+# or
+yarn
+yarn dev
+```
+
+Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download)):
+
+```bash
+now
+```
+
+## The idea behind the example
+
+[GraphQL Hooks](https://github.com/nearform/graphql-hooks) is a library from NearForm that intends to be a minimal hooks-first GraphQL client. Providing a similar API to Apollo.
+
+You'll see this shares the same [graph.cool](https://www.graph.cool) backend as the Apollo example, this is so you can compare the two side by side. The app itself should also look identical.
diff --git a/examples/with-graphql-hooks/components/app.js b/examples/with-graphql-hooks/components/app.js
new file mode 100644
index 0000000000000..ec15c11f569e8
--- /dev/null
+++ b/examples/with-graphql-hooks/components/app.js
@@ -0,0 +1,42 @@
+export default ({ children }) => (
+
+ {children}
+
+
+)
diff --git a/examples/with-graphql-hooks/components/error-message.js b/examples/with-graphql-hooks/components/error-message.js
new file mode 100644
index 0000000000000..8497a5d2df95a
--- /dev/null
+++ b/examples/with-graphql-hooks/components/error-message.js
@@ -0,0 +1,13 @@
+export default ({ message }) => (
+
+)
diff --git a/examples/with-graphql-hooks/components/header.js b/examples/with-graphql-hooks/components/header.js
new file mode 100644
index 0000000000000..392b7d962f4e1
--- /dev/null
+++ b/examples/with-graphql-hooks/components/header.js
@@ -0,0 +1,28 @@
+import Link from 'next/link'
+import { withRouter } from 'next/router'
+
+const Header = ({ router: { pathname } }) => (
+
+
+ Home
+
+
+ About
+
+
+
+)
+
+export default withRouter(Header)
diff --git a/examples/with-graphql-hooks/components/post-list.js b/examples/with-graphql-hooks/components/post-list.js
new file mode 100644
index 0000000000000..64e9b521fc182
--- /dev/null
+++ b/examples/with-graphql-hooks/components/post-list.js
@@ -0,0 +1,112 @@
+import React, { Fragment, useState } from 'react'
+import { useQuery } from 'graphql-hooks'
+import ErrorMessage from './error-message'
+import PostUpvoter from './post-upvoter'
+import Submit from './submit'
+
+export const allPostsQuery = `
+ query allPosts($first: Int!, $skip: Int!) {
+ allPosts(orderBy: createdAt_DESC, first: $first, skip: $skip) {
+ id
+ title
+ votes
+ url
+ createdAt
+ }
+ _allPostsMeta {
+ count
+ }
+ }
+`
+
+export default function PostList () {
+ const [skip, setSkip] = useState(0)
+ const { loading, error, data, refetch } = useQuery(allPostsQuery, {
+ variables: { skip, first: 10 },
+ updateData: (prevResult, result) => ({
+ ...result,
+ allPosts: [...prevResult.allPosts, ...result.allPosts]
+ })
+ })
+
+ if (error) return
+ if (!data) return
+ {areMorePosts ? (
+
+ ) : (
+ ''
+ )}
+
+
+
+ )
+}
diff --git a/examples/with-graphql-hooks/components/post-upvoter.js b/examples/with-graphql-hooks/components/post-upvoter.js
new file mode 100644
index 0000000000000..bc9fd00a1c4a5
--- /dev/null
+++ b/examples/with-graphql-hooks/components/post-upvoter.js
@@ -0,0 +1,57 @@
+import React from 'react'
+import { useMutation } from 'graphql-hooks'
+
+const UPDATE_POST = `
+ mutation updatePost($id: ID!, $votes: Int) {
+ updatePost(id: $id, votes: $votes) {
+ id
+ __typename
+ votes
+ }
+ }
+`
+
+export default function PostUpvoter ({ votes, id, onUpdate }) {
+ const [updatePost] = useMutation(UPDATE_POST)
+
+ return (
+
+ )
+}
diff --git a/examples/with-graphql-hooks/components/submit.js b/examples/with-graphql-hooks/components/submit.js
new file mode 100644
index 0000000000000..b3b9894800fe3
--- /dev/null
+++ b/examples/with-graphql-hooks/components/submit.js
@@ -0,0 +1,56 @@
+import React from 'react'
+import { useMutation } from 'graphql-hooks'
+
+const CREATE_POST = `
+mutation createPost($title: String!, $url: String!) {
+ createPost(title: $title, url: $url) {
+ id
+ title
+ votes
+ url
+ createdAt
+ }
+}`
+
+export default function Submit ({ onSubmission }) {
+ const [createPost, state] = useMutation(CREATE_POST)
+
+ return (
+
+ )
+}
+
+async function handleSubmit (event, onSubmission, createPost) {
+ event.preventDefault()
+ const form = event.target
+ const formData = new window.FormData(form)
+ const title = formData.get('title')
+ const url = formData.get('url')
+ form.reset()
+ const result = await createPost({
+ variables: {
+ title,
+ url
+ }
+ })
+ onSubmission && onSubmission(result)
+}
diff --git a/examples/with-graphql-hooks/lib/init-graphql.js b/examples/with-graphql-hooks/lib/init-graphql.js
new file mode 100644
index 0000000000000..c3041cad282a2
--- /dev/null
+++ b/examples/with-graphql-hooks/lib/init-graphql.js
@@ -0,0 +1,29 @@
+import { GraphQLClient } from 'graphql-hooks'
+import memCache from 'graphql-hooks-memcache'
+import unfetch from 'isomorphic-unfetch'
+
+let graphQLClient = null
+
+function create (initialState = {}) {
+ return new GraphQLClient({
+ ssrMode: !process.browser,
+ url: 'https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn',
+ cache: memCache({ initialState }),
+ fetch: process.browser ? fetch.bind() : unfetch // eslint-disable-line
+ })
+}
+
+export default function initGraphQL (initialState) {
+ // Make sure to create a new client for every server-side request so that data
+ // isn't shared between connections (which would be bad)
+ if (!process.browser) {
+ return create(initialState)
+ }
+
+ // Reuse client on the client-side
+ if (!graphQLClient) {
+ graphQLClient = create(initialState)
+ }
+
+ return graphQLClient
+}
diff --git a/examples/with-graphql-hooks/lib/with-graphql-client.js b/examples/with-graphql-hooks/lib/with-graphql-client.js
new file mode 100644
index 0000000000000..e58e894042cb9
--- /dev/null
+++ b/examples/with-graphql-hooks/lib/with-graphql-client.js
@@ -0,0 +1,62 @@
+import React from 'react'
+import initGraphQL from './init-graphql'
+import Head from 'next/head'
+import { getInitialState } from 'graphql-hooks-ssr'
+
+export default App => {
+ return class GraphQLHooks extends React.Component {
+ static displayName = 'GraphQLHooks(App)'
+ static async getInitialProps (ctx) {
+ const { Component, router } = ctx
+
+ let appProps = {}
+ if (App.getInitialProps) {
+ appProps = await App.getInitialProps(ctx)
+ }
+
+ // Run all GraphQL queries in the component tree
+ // and extract the resulting data
+ const graphQLClient = initGraphQL()
+ let graphQLState = {}
+ if (!process.browser) {
+ try {
+ // Run all GraphQL queries
+ graphQLState = await getInitialState({
+ App: (
+
+ ),
+ client: graphQLClient
+ })
+ } catch (error) {
+ // Prevent GraphQL hooks client errors from crashing SSR.
+ // Handle them in components via the state.error prop:
+ // https://github.com/nearform/graphql-hooks#usequery
+ console.error('Error while running `getInitialState`', error)
+ }
+
+ // getInitialState does not call componentWillUnmount
+ // head side effect therefore need to be cleared manually
+ Head.rewind()
+ }
+
+ return {
+ ...appProps,
+ graphQLState
+ }
+ }
+
+ constructor (props) {
+ super(props)
+ this.graphQLClient = initGraphQL(props.graphQLState)
+ }
+
+ render () {
+ return
+ }
+ }
+}
diff --git a/examples/with-graphql-hooks/next.config.js b/examples/with-graphql-hooks/next.config.js
new file mode 100644
index 0000000000000..0fbd0e535c8f4
--- /dev/null
+++ b/examples/with-graphql-hooks/next.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ target: 'serverless'
+}
diff --git a/examples/with-graphql-hooks/now.json b/examples/with-graphql-hooks/now.json
new file mode 100644
index 0000000000000..7a22023c122af
--- /dev/null
+++ b/examples/with-graphql-hooks/now.json
@@ -0,0 +1,5 @@
+{
+ "version": 2,
+ "name": "next-with-graphql-hooks",
+ "builds": [{ "src": "next.config.js", "use": "@now/next" }]
+}
diff --git a/examples/with-graphql-hooks/package.json b/examples/with-graphql-hooks/package.json
new file mode 100644
index 0000000000000..4d7d4e0f6072c
--- /dev/null
+++ b/examples/with-graphql-hooks/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "with-graphql-hooks",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "dev": "next",
+ "build": "next build",
+ "start": "next start",
+ "now-build": "next build"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "graphql-hooks": "^3.2.1",
+ "graphql-hooks-memcache": "^1.0.4",
+ "graphql-hooks-ssr": "^1.0.1",
+ "isomorphic-unfetch": "^3.0.0",
+ "next": "^8.0.1",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.2",
+ "react-dom": "^16.8.2"
+ }
+}
diff --git a/examples/with-graphql-hooks/pages/_app.js b/examples/with-graphql-hooks/pages/_app.js
new file mode 100644
index 0000000000000..cf8846a5498fe
--- /dev/null
+++ b/examples/with-graphql-hooks/pages/_app.js
@@ -0,0 +1,19 @@
+import App, { Container } from 'next/app'
+import React from 'react'
+import withGraphQLClient from '../lib/with-graphql-client'
+import { ClientContext } from 'graphql-hooks'
+
+class MyApp extends App {
+ render () {
+ const { Component, pageProps, graphQLClient } = this.props
+ return (
+
+
+
+
+
+ )
+ }
+}
+
+export default withGraphQLClient(MyApp)
diff --git a/examples/with-graphql-hooks/pages/about.js b/examples/with-graphql-hooks/pages/about.js
new file mode 100644
index 0000000000000..88970a29f5b46
--- /dev/null
+++ b/examples/with-graphql-hooks/pages/about.js
@@ -0,0 +1,30 @@
+import App from '../components/app'
+import Header from '../components/header'
+
+export default () => (
+
+
+
+
The Idea Behind This Example
+
+ GraphQL Hooks is
+ a library from NearForm that intends to be a minimal hooks-first GraphQL
+ client. Providing it in a way familiar to Apollo users.
+
+
+
+ This started life as a copy of the `with-apollo` example. We then
+ stripped out Apollo and replaced it with `graphql-hooks`. This was
+ mostly as an exercise in ensuring basic functionality could be achieved
+ in a similar way to Apollo.
+
+
+
+ You'll see this shares the same{' '}
+ graph.cool backend as the Apollo
+ example, this is so you can compare the two side by side. The app itself
+ should also look identical.
+
+
+
+)
diff --git a/examples/with-graphql-hooks/pages/index.js b/examples/with-graphql-hooks/pages/index.js
new file mode 100644
index 0000000000000..22a7b48c7cf17
--- /dev/null
+++ b/examples/with-graphql-hooks/pages/index.js
@@ -0,0 +1,10 @@
+import App from '../components/app'
+import Header from '../components/header'
+import PostList from '../components/post-list'
+
+export default () => (
+
+
+
+
+)