Skip to content

Commit

Permalink
fix: preserve clients-side apollo cache between pages
Browse files Browse the repository at this point in the history
  • Loading branch information
Rupert Redington committed Nov 22, 2021
1 parent d5e7222 commit 4611372
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 230 deletions.
19 changes: 0 additions & 19 deletions src/api-client/operations/minimumViableLooResponse.graphql

This file was deleted.

151 changes: 0 additions & 151 deletions src/api-client/staticPage.tsx

This file was deleted.

55 changes: 29 additions & 26 deletions src/api/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,33 +103,36 @@ const resolvers = {
loosByProximity: async (parent, args) =>
await Loo.findNear(args.from.lng, args.from.lat, args.from.maxDistance),
ukLooMarkers: async () => {
const loos = await Loo.find({'properties.active': true}).where('properties.geometry').within({
type: 'Polygon',
coordinates: [[
[
-0.3515625,
61.44927080076419
const loos = await Loo.find({ 'properties.active': true })
.where('properties.geometry')
.within({
type: 'Polygon',
coordinates: [
[
[-0.3515625, 61.44927080076419],
[-15.5126953125, 55.7642131648377],
[-7.66845703125, 48.151428143221224],
[2.35107421875, 51.34433866059924],
[-0.3515625, 61.44927080076419],
],
],
[
-15.5126953125,
55.7642131648377
],
[
-7.66845703125,
48.151428143221224
],
[
2.35107421875,
51.34433866059924
],
[
-0.3515625,
61.44927080076419
]
]]
});
return loos.map(loo => {
return `${loo.id}|${loo.properties.geometry.coordinates[0].toFixed(4)}|${loo.properties.geometry.coordinates[1].toFixed(4)}|${loo.properties.name ? loo.properties.name.replace('|', ' ') : ''}`;
});
/**
* TODO: add some data for map-filters:
* noPayment
* allGender
* automatic
* accessible
* babyChange
* radar
* campaignUOL
**/
return loos.map((loo) => {
return `${loo.id}|${loo.properties.geometry.coordinates[0].toFixed(
4
)}|${loo.properties.geometry.coordinates[1].toFixed(4)}|${
loo.properties.name ? loo.properties.name.replace('|', ' ') : ''
}`;
});
},
areas: async (parent, args) => {
Expand Down
88 changes: 54 additions & 34 deletions src/components/withApollo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { NextPage } from 'next';
import merge from 'deepmerge';
import isEqual from 'lodash/isEqual';

import {
ApolloClient,
Expand All @@ -7,55 +9,73 @@ import {
ApolloProvider,
createHttpLink,
} from '@apollo/client';
import {
NextApiRequestCookies,
// @ts-ignore This path is generated at build time and conflicts otherwise
} from 'next-server/server/api-utils';
import { IncomingMessage } from 'http';

export type ApolloClientContext = {
req?: IncomingMessage & {
cookies: NextApiRequestCookies;
};
};

export const withApollo = (Comp: NextPage) =>
function ApolloWrapper(props: any) {
return (
<ApolloProvider client={getApolloClient(undefined, props.apolloState)}>
<Comp />
</ApolloProvider>
);
};
let apolloClient: ApolloClient<NormalizedCacheObject> | undefined;

/**
* Refactor this to reuse any existing apolloclinet in the client-side
* merge the initialState from the pageprops with the client's current state see: https://developers.wpengine.com/blog/apollo-client-cache-rehydration-in-next-js
*/
export const getApolloClient = (
ctx?: ApolloClientContext,
initialState?: NormalizedCacheObject
) => {
function createApolloClient() {
let link;
if (typeof window === 'undefined') {
const { SchemaLink } = require('@apollo/client/link/schema');
const { schema } = require('../pages/api');
link = new SchemaLink({ schema });
} else {
const url =
process.env.NODE_ENV === 'development'
? process.env.AUTH0_BASE_URL
: process.env.VERCEL_URL;
link = createHttpLink({
uri: typeof window === 'undefined' ? url + '/api' : '/api',
uri: '/api',
credentials: 'same-origin',
fetch,
});
}

const cache = new InMemoryCache().restore(initialState || {});
const cache = new InMemoryCache();
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link,
cache,
});
};
}

/**
* The big trick here is to merge the initialState from the pageprops with the client's current state see: https://developers.wpengine.com/blog/apollo-client-cache-rehydration-in-next-js
* When we don't do theis the accumulates apolloState gets wiped out by any incoming static page props
*/
export function getApolloClient(
initialState: NormalizedCacheObject | null = null
) {
const _apolloClient = apolloClient ?? createApolloClient();
// If a 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, {
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 const withApollo = (Comp: NextPage) =>
function ApolloWrapper(props: any) {
return (
<ApolloProvider client={getApolloClient(props.apolloState)}>
<Comp />
</ApolloProvider>
);
};

0 comments on commit 4611372

Please sign in to comment.