Skip to content

Commit 20d8823

Browse files
authored
Make withApollo work with _app.js components (vercel#8801)
* Make withApollo work with _app.js components * Support wrapping functional _App * Add apolloClient to NextPageContext & NextPageContext * Propertly call App.getInitialProps if used in NextAppContext * Add Automatic Static Optimization warning
1 parent 9dc0afd commit 20d8823

File tree

1 file changed

+40
-15
lines changed

1 file changed

+40
-15
lines changed

examples/with-apollo/lib/apollo.js

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react'
2+
import App from 'next/app'
23
import Head from 'next/head'
34
import { ApolloProvider } from '@apollo/react-hooks'
45
import { ApolloClient } from 'apollo-client'
@@ -28,25 +29,44 @@ export const withApollo = ({ ssr = true } = {}) => PageComponent => {
2829
const displayName =
2930
PageComponent.displayName || PageComponent.name || 'Component'
3031

31-
if (displayName === 'App') {
32-
console.warn('This withApollo HOC only works with PageComponents.')
33-
}
34-
3532
WithApollo.displayName = `withApollo(${displayName})`
3633
}
3734

3835
if (ssr || PageComponent.getInitialProps) {
3936
WithApollo.getInitialProps = async ctx => {
4037
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+
}
4148

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+
}
4563

4664
// Run wrapped getInitialProps methods
4765
let pageProps = {}
4866
if (PageComponent.getInitialProps) {
4967
pageProps = await PageComponent.getInitialProps(ctx)
68+
} else if (inAppContext) {
69+
pageProps = await App.getInitialProps(ctx)
5070
}
5171

5272
// Only on the server:
@@ -62,14 +82,19 @@ export const withApollo = ({ ssr = true } = {}) => PageComponent => {
6282
try {
6383
// Run all GraphQL queries
6484
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} />)
7398
} catch (error) {
7499
// Prevent Apollo Client GraphQL errors from crashing SSR.
75100
// Handle them in components via the data.error prop:

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy