forked from vercel/next.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor api-routes-apollo-server-and-client example (vercel#8673)
* Remove connectToDevTools in favour of better default Disabled devtools in production * Refactor api-routes-apollo-server-and-client example
- Loading branch information
Showing
6 changed files
with
156 additions
and
126 deletions.
There are no files selected for viewing
151 changes: 151 additions & 0 deletions
151
examples/api-routes-apollo-server-and-client/apollo/client.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import React, { useMemo } from 'react' | ||
import Head from 'next/head' | ||
import { ApolloProvider } from '@apollo/react-hooks' | ||
import { ApolloClient } from 'apollo-client' | ||
import { InMemoryCache } from 'apollo-cache-inmemory' | ||
|
||
let apolloClient = null | ||
|
||
/** | ||
* Creates and provides the apolloContext | ||
* to a next.js PageTree. Use it by wrapping | ||
* your PageComponent via HOC pattern. | ||
* @param {Function|Class} PageComponent | ||
* @param {Object} [config] | ||
* @param {Boolean} [config.ssr=true] | ||
*/ | ||
export function withApollo (PageComponent, { ssr = true } = {}) { | ||
const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => { | ||
const client = useMemo( | ||
() => apolloClient || initApolloClient(apolloState), | ||
[] | ||
) | ||
return ( | ||
<ApolloProvider client={client}> | ||
<PageComponent {...pageProps} /> | ||
</ApolloProvider> | ||
) | ||
} | ||
|
||
// Set the correct displayName in development | ||
if (process.env.NODE_ENV !== 'production') { | ||
const displayName = | ||
PageComponent.displayName || PageComponent.name || 'Component' | ||
|
||
if (displayName === 'App') { | ||
console.warn('This withApollo HOC only works with PageComponents.') | ||
} | ||
|
||
WithApollo.displayName = `withApollo(${displayName})` | ||
} | ||
|
||
if (ssr || PageComponent.getInitialProps) { | ||
WithApollo.getInitialProps = async ctx => { | ||
const { AppTree } = ctx | ||
|
||
// Initialize ApolloClient, add it to the ctx object so | ||
// we can use it in `PageComponent.getInitialProp`. | ||
const apolloClient = (ctx.apolloClient = initApolloClient()) | ||
|
||
// Run wrapped getInitialProps methods | ||
let pageProps = {} | ||
if (PageComponent.getInitialProps) { | ||
pageProps = await PageComponent.getInitialProps(ctx) | ||
} | ||
|
||
// Only on the server: | ||
if (typeof window === 'undefined') { | ||
// When redirecting, the response is finished. | ||
// No point in continuing to render | ||
if (ctx.res && ctx.res.finished) { | ||
return pageProps | ||
} | ||
|
||
// Only if ssr is enabled | ||
if (ssr) { | ||
try { | ||
// Run all GraphQL queries | ||
const { getDataFromTree } = await import('@apollo/react-ssr') | ||
await getDataFromTree( | ||
<AppTree | ||
pageProps={{ | ||
...pageProps, | ||
apolloClient | ||
}} | ||
/> | ||
) | ||
} catch (error) { | ||
// Prevent Apollo Client GraphQL errors from crashing SSR. | ||
// Handle them in components via the data.error prop: | ||
// https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error | ||
console.error('Error while running `getDataFromTree`', error) | ||
} | ||
|
||
// getDataFromTree does not call componentWillUnmount | ||
// head side effect therefore need to be cleared manually | ||
Head.rewind() | ||
} | ||
} | ||
|
||
// Extract query data from the Apollo store | ||
const apolloState = apolloClient.cache.extract() | ||
|
||
return { | ||
...pageProps, | ||
apolloState | ||
} | ||
} | ||
} | ||
|
||
return WithApollo | ||
} | ||
|
||
/** | ||
* Always creates a new apollo client on the server | ||
* Creates or reuses apollo client in the browser. | ||
* @param {Object} initialState | ||
*/ | ||
function initApolloClient (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 (typeof window === 'undefined') { | ||
return createApolloClient(initialState) | ||
} | ||
|
||
// Reuse client on the client-side | ||
if (!apolloClient) { | ||
apolloClient = createApolloClient(initialState) | ||
} | ||
|
||
return apolloClient | ||
} | ||
|
||
/** | ||
* Creates and configures the ApolloClient | ||
* @param {Object} [initialState={}] | ||
*/ | ||
function createApolloClient (initialState = {}) { | ||
const ssrMode = typeof window === 'undefined' | ||
const cache = new InMemoryCache().restore(initialState) | ||
|
||
// Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient | ||
return new ApolloClient({ | ||
ssrMode, | ||
link: createIsomorphLink(), | ||
cache | ||
}) | ||
} | ||
|
||
function createIsomorphLink () { | ||
if (typeof window === 'undefined') { | ||
const { SchemaLink } = require('apollo-link-schema') | ||
const { schema } = require('./schema') | ||
return new SchemaLink({ schema }) | ||
} else { | ||
const { HttpLink } = require('apollo-link-http') | ||
return new HttpLink({ | ||
uri: '/api/graphql', | ||
credentials: 'same-origin' | ||
}) | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
examples/api-routes-apollo-server-and-client/apollo/resolvers.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
export const resolvers = { | ||
Query: { | ||
viewer (_parent, _args, _context, _info) { | ||
return { name: 'John Smith', id: 1 } | ||
return { id: 1, name: 'John Smith', status: 'cached' } | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ export const typeDefs = gql` | |
type User { | ||
id: ID! | ||
name: String! | ||
status: String! | ||
} | ||
type Query { | ||
|
56 changes: 0 additions & 56 deletions
56
examples/api-routes-apollo-server-and-client/lib/init-apollo.js
This file was deleted.
Oops, something went wrong.
62 changes: 0 additions & 62 deletions
62
examples/api-routes-apollo-server-and-client/lib/with-apollo-client.js
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters