Skip to content

Instantly share code, notes, and snippets.

@KevinDanikowski
Created July 27, 2020 18:59
Show Gist options
  • Save KevinDanikowski/ca2b0b10eb6f1f871bd8538a1c93e1c0 to your computer and use it in GitHub Desktop.
Save KevinDanikowski/ca2b0b10eb6f1f871bd8538a1c93e1c0 to your computer and use it in GitHub Desktop.
// I'VE COPIED WHOLE FILE FOR REFERENCE, ONLY THE HEADERS PART HAS CHANGED
// THIS FILE: https://github.com/amclin/react-project-boilerplate/blob/master/templates/default/src/utils/apollo.jsx
/* eslint-disable react/jsx-props-no-spreading, no-console */
/* FOR SERVER SIDE RENDERING APOLLO FETCHES: Use unmodifed link below.
* https://github.com/zeit/next.js/blob/canary/examples/with-apollo/lib/apollo.js
* this file is modified from link above. Had some issues getting it to work with hooks.
*/
import React from 'react'
import { ApolloProvider } from '@apollo/react-hooks'
import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client'
import fetch from 'isomorphic-unfetch'
import getConfig from 'next/config'
import { setContext } from '@apollo/client/link/context'
import { AWS_ACCESS_TOKEN } from 'Utils/constants'
const {
publicRuntimeConfig: {
urls: { proxyServer: apiGatewayUrl },
},
} = getConfig()
export let apolloClient = null
const httpLink = createHttpLink({
uri: apiGatewayUrl,
fetch,
})
const authLink = setContext((_, { headers }) => {
// get the authentication token from local storage if it exists
const token = localStorage.getItem(AWS_ACCESS_TOKEN)
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
},
}
})
/**
* Creates and configures the ApolloClient
* @param {Object} [initialState={}]
*/
function createApolloClient(initialState = {}) {
return new ApolloClient({
ssrMode: false, // !process.browser - turn this on if you need to make calls before sending html page
link: authLink.concat(httpLink),
cache: new InMemoryCache().restore(initialState),
})
}
/**
* 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 (!process.browser) {
return createApolloClient(initialState)
}
// Reuse client on the client-side
if (!apolloClient) {
apolloClient = createApolloClient(initialState)
}
return apolloClient
}
/**
* 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]
*/
export function withApollo(PageComponent) {
// eslint-disable-next-line
const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
const client = apolloClient || initApolloClient(apolloState)
return (
<ApolloProvider client={client}>
<PageComponent {...pageProps} />
</ApolloProvider>
)
}
// unused, we do server rendered optimized, so no getInitialProps
if (PageComponent.getInitialProps) {
WithApollo.getInitialProps = async ctx => {
// Initialize ApolloClient, add it to the ctx object so
// we can use it in `PageComponent.getInitialProp`.
// eslint-disable-next-line
const apolloClient = (ctx.apolloClient = initApolloClient())
// Run wrapped getInitialProps methods
const pageProps = await PageComponent.getInitialProps(ctx)
// Only on the server:
if (!process.browser) {
// When redirecting, the response is finished.
// No point in continuing to render
if (ctx.res && ctx.res.finished) {
return pageProps
}
}
// Extract query data from the Apollo store
const apolloState = apolloClient.cache.extract()
return {
...pageProps,
apolloState,
}
}
}
return WithApollo
}
export default withApollo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment