Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Examples] Move with-apollo to SSG #13742

Merged
merged 19 commits into from
Jun 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions examples/with-apollo/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
# Apollo Example

[Apollo](https://www.apollographql.com/client/) is a GraphQL client that allows you to easily query the exact data you need from a GraphQL server. In addition to fetching and mutating data, Apollo analyzes your queries and their results to construct a client-side cache of your data, which is kept up to date as further queries and mutations are run, fetching more results from the server.
[Apollo](https://www.apollographql.com/client/) is a GraphQL client that allows you to easily query the exact data you need from a GraphQL server. In addition to fetching and mutating data, Apollo analyzes your queries and their results to construct a client-side cache of your data, which is kept up to date as further queries and mutations are run.

In this simple example, we integrate Apollo seamlessly with Next by wrapping our `pages/index.js` inside a [higher-order component (HOC)](https://facebook.github.io/react/docs/higher-order-components.html). Using the HOC pattern we're able to pass down a central store of query result data created by Apollo into our React component hierarchy defined inside each page of our Next application.

On initial page load, while on the server and inside `getInitialProps`, we invoke the Apollo method, [`getDataFromTree`](https://www.apollographql.com/docs/react/api/react-ssr/#getdatafromtree). This method returns a promise; at the point in which the promise resolves, our Apollo Client store is completely initialized.
In this simple example, we integrate Apollo seamlessly with [Next.js data fetching methods](https://nextjs.org/docs/basic-features/data-fetching) to fetch queries in the server and hydrate them in the browser.

This example relies on [graph.cool](https://www.graph.cool) for its GraphQL backend.

Note: Do not be alarmed that you see two renders being executed. Apollo recursively traverses the React render tree looking for Apollo query components. When it has done that, it fetches all these queries and then passes the result to a cache. This cache is then used to render the data on the server side (another React render).
https://www.apollographql.com/docs/react/api/react-ssr/#getdatafromtree
## Demo

[https://next-with-apollo.now.sh](https://next-with-apollo.now.sh)

## Deploy your own

Deploy the example using [Vercel](https://vercel.com):

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/vercel/next.js/tree/canary/examples/with-apollo)

_Live Example: https://next-with-apollo.now.sh_

## How to use

### Using `create-next-app`
Expand Down
16 changes: 0 additions & 16 deletions examples/with-apollo/apolloClient.js

This file was deleted.

62 changes: 32 additions & 30 deletions examples/with-apollo/components/Header.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import { useRouter } from 'next/router'
import Link from 'next/link'
import { withRouter } from 'next/router'

const Header = ({ router: { pathname } }) => (
<header>
<Link href="/">
<a className={pathname === '/' ? 'is-active' : ''}>Home</a>
</Link>
<Link href="/client-only">
<a className={pathname === '/client-only' ? 'is-active' : ''}>
Client-Only
</a>
</Link>
<Link href="/about">
<a className={pathname === '/about' ? 'is-active' : ''}>About</a>
</Link>
<style jsx>{`
header {
margin-bottom: 25px;
}
a {
font-size: 14px;
margin-right: 15px;
text-decoration: none;
}
.is-active {
text-decoration: underline;
}
`}</style>
</header>
)
export default function Header() {
const { pathname } = useRouter()

export default withRouter(Header)
return (
<header>
<Link href="/">
<a className={pathname === '/' ? 'is-active' : ''}>Home</a>
</Link>
<Link href="/about">
<a className={pathname === '/about' ? 'is-active' : ''}>About</a>
</Link>
<Link href="/client-only">
<a className={pathname === '/client-only' ? 'is-active' : ''}>
Client-Only
</a>
</Link>
<style jsx>{`
header {
margin-bottom: 25px;
}
a {
font-size: 14px;
margin-right: 15px;
text-decoration: none;
}
.is-active {
text-decoration: underline;
}
`}</style>
</header>
)
}
1 change: 1 addition & 0 deletions examples/with-apollo/components/PostList.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const ALL_POSTS_QUERY = gql`
}
}
`

export const allPostsQueryVars = {
skip: 0,
first: 10,
Expand Down
175 changes: 0 additions & 175 deletions examples/with-apollo/lib/apollo.js

This file was deleted.

38 changes: 38 additions & 0 deletions examples/with-apollo/lib/apolloClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useMemo } from 'react'
import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { HttpLink } from 'apollo-link-http'

let apolloClient

function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: new HttpLink({
uri: 'https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn', // Server URL (must be absolute)
credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
}),
cache: new InMemoryCache(),
})
}

export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient()

// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// get hydrated here
if (initialState) {
_apolloClient.cache.restore(initialState)
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient

return _apolloClient
}

export function useApollo(initialState) {
const store = useMemo(() => initializeApollo(initialState), [initialState])
return store
}
7 changes: 3 additions & 4 deletions examples/with-apollo/package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
{
"name": "with-apollo",
"version": "2.0.0",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@apollo/react-hooks": "3.1.3",
"@apollo/react-ssr": "3.1.3",
"apollo-cache-inmemory": "1.6.5",
"apollo-client": "2.6.8",
"apollo-link-http": "1.5.16",
Expand All @@ -19,8 +18,8 @@
"react": "^16.7.0",
"react-dom": "^16.7.0"
},
"license": "ISC",
"devDependencies": {
"babel-plugin-graphql-tag": "^2.5.0"
}
},
"license": "ISC"
}
12 changes: 12 additions & 0 deletions examples/with-apollo/pages/_app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ApolloProvider } from '@apollo/react-hooks'
import { useApollo } from '../lib/apolloClient'

export default function App({ Component, pageProps }) {
const apolloClient = useApollo(pageProps.initialApolloState)

return (
<ApolloProvider client={apolloClient}>
<Component {...pageProps} />
</ApolloProvider>
)
}
Loading