1
1
import React from 'react'
2
+ import App from 'next/app'
2
3
import Head from 'next/head'
3
4
import { ApolloProvider } from '@apollo/react-hooks'
4
5
import { ApolloClient } from 'apollo-client'
@@ -28,25 +29,44 @@ export const withApollo = ({ ssr = true } = {}) => PageComponent => {
28
29
const displayName =
29
30
PageComponent . displayName || PageComponent . name || 'Component'
30
31
31
- if ( displayName === 'App' ) {
32
- console . warn ( 'This withApollo HOC only works with PageComponents.' )
33
- }
34
-
35
32
WithApollo . displayName = `withApollo(${ displayName } )`
36
33
}
37
34
38
35
if ( ssr || PageComponent . getInitialProps ) {
39
36
WithApollo . getInitialProps = async ctx => {
40
37
const { AppTree } = ctx
38
+ const inAppContext = Boolean ( ctx . ctx )
39
+
40
+ if ( process . env . NODE_ENV === 'development' ) {
41
+ if ( inAppContext ) {
42
+ console . warn (
43
+ 'Warning: You have opted-out of Automatic Static Optimization due to `withApollo` in `pages/_app`.\n' +
44
+ 'Read more: https://err.sh/next.js/opt-out-auto-static-optimization\n'
45
+ )
46
+ }
47
+ }
41
48
42
- // Initialize ApolloClient, add it to the ctx object so
43
- // we can use it in `PageComponent.getInitialProp`.
44
- const apolloClient = ( ctx . apolloClient = initApolloClient ( ) )
49
+ if ( ctx . apolloClient ) {
50
+ throw new Error ( 'Multiple instances of withApollo found.' )
51
+ }
52
+
53
+ // Initialize ApolloClient
54
+ const apolloClient = initApolloClient ( )
55
+
56
+ // Add apolloClient to NextPageContext & NextAppContext
57
+ // This allows us to consume the apolloClient inside our
58
+ // custom `getInitialProps({ apolloClient })`.
59
+ ctx . apolloClient = apolloClient
60
+ if ( inAppContext ) {
61
+ ctx . ctx . apolloClient = apolloClient
62
+ }
45
63
46
64
// Run wrapped getInitialProps methods
47
65
let pageProps = { }
48
66
if ( PageComponent . getInitialProps ) {
49
67
pageProps = await PageComponent . getInitialProps ( ctx )
68
+ } else if ( inAppContext ) {
69
+ pageProps = await App . getInitialProps ( ctx )
50
70
}
51
71
52
72
// Only on the server:
@@ -62,14 +82,19 @@ export const withApollo = ({ ssr = true } = {}) => PageComponent => {
62
82
try {
63
83
// Run all GraphQL queries
64
84
const { getDataFromTree } = await import ( '@apollo/react-ssr' )
65
- await getDataFromTree (
66
- < AppTree
67
- pageProps = { {
68
- ...pageProps ,
69
- apolloClient,
70
- } }
71
- />
72
- )
85
+
86
+ // Since AppComponents and PageComponents have different context types
87
+ // we need to modify their props a little.
88
+ let props
89
+ if ( inAppContext ) {
90
+ props = { ...pageProps , apolloClient }
91
+ } else {
92
+ props = { pageProps : { ...pageProps , apolloClient } }
93
+ }
94
+
95
+ // Takes React AppTree, determine which queries are needed to render,
96
+ // then fetche them all.
97
+ await getDataFromTree ( < AppTree { ...props } /> )
73
98
} catch ( error ) {
74
99
// Prevent Apollo Client GraphQL errors from crashing SSR.
75
100
// Handle them in components via the data.error prop:
0 commit comments