Skip to content

Instantly share code, notes, and snippets.

@ardiewen
Last active July 28, 2021 01:55
Show Gist options
  • Save ardiewen/e7927b78a652cd0e4108fc53c5fa742b to your computer and use it in GitHub Desktop.
Save ardiewen/e7927b78a652cd0e4108fc53c5fa742b to your computer and use it in GitHub Desktop.
Example of modifying the existing "with-apollo" NextJS example with wp-graphql-woocommerce middleware.
import { useMemo } from 'react'
import { ApolloClient, InMemoryCache, from } from '@apollo/client'
import merge from 'deepmerge'
import isEqual from 'lodash/isEqual'
import {
httpLink,
onErrorLink,
wooSessionMiddleware,
wooSessionAfterware,
} from 'lib/apollo/middleware'
export const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__'
let apolloClient
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: from([
onErrorLink,
wooSessionMiddleware,
wooSessionAfterware,
httpLink,
]),
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
// gets hydrated here
if (initialState) {
// Get existing cache, loaded during client side data fetching
const existingCache = _apolloClient.extract()
// Merge the existing cache into data passed from getStaticProps/getServerSideProps
const data = merge(initialState, existingCache, {
// combine arrays using object equality (like in sets)
arrayMerge: (destinationArray, sourceArray) => [
...sourceArray,
...destinationArray.filter((d) =>
sourceArray.every((s) => !isEqual(d, s))
),
],
})
// Restore the cache with the merged data
_apolloClient.cache.restore(data)
}
// 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 addApolloState(client, pageProps) {
if (pageProps?.props) {
pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract()
}
return pageProps
}
export function useApollo(pageProps) {
const state = pageProps[APOLLO_STATE_PROP_NAME]
const store = useMemo(() => initializeApollo(state), [state])
return store
}
import { HttpLink, ApolloLink } from '@apollo/client'
import { onError } from '@apollo/client/link/error'
const isBrowser = typeof window !== 'undefined'
const httpLink = new HttpLink({
uri: process.env.NEXT_PUBLIC_GRAPHQL_URL,
credentials: 'include',
fetch,
})
const onErrorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path, extensions }) => {
// if (extensions && extensions.code === 'invalid-jwt') {
// logout(() => Router.push('/'))
// }
console.log(`[GraphQL error]:`, {
Message: message,
Location: locations,
Path: path,
Extension: extensions,
})
})
}
if (networkError) {
console.log(`[Network error]: ${networkError}`)
}
})
const wooSessionMiddleware = new ApolloLink((operation, forward) => {
/**
* If session data exist in local storage, set value as session header.
*/
const session = isBrowser && window.localStorage.getItem('woo-session')
if (session) {
operation.setContext(({ headers = {} }) => ({
headers: {
...headers, // spread existing headers, e.g. authentication
'woocommerce-session': `Session ${session}`,
},
}))
}
return forward(operation)
})
const wooSessionAfterware = new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
/**
* Check for session header and update session in local storage accordingly.
*/
const context = operation.getContext()
const {
response: { headers },
} = context
const session = headers.get('woocommerce-session')
if (session) {
// remove session data if session destroyed.
if ('false' === session) {
isBrowser && window.localStorage.removeItem('woo-session')
// update session new data if changed.
} else if (
isBrowser &&
window.localStorage.getItem('woo-session') !== session
) {
window.localStorage.setItem(
'woo-session',
headers.get('woocommerce-session')
)
}
}
return response
})
})
export {
httpLink,
// authMiddleware,
onErrorLink,
wooSessionMiddleware,
wooSessionAfterware,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment