Skip to content

Commit

Permalink
Upgrade meetup demo usage of NextJS latest pattern (#3229)
Browse files Browse the repository at this point in the history
Ref: https://github.com/vercel/next.js/blob/canary/examples/with-apollo

The summary of the changes are:
- Less boilerplate code for setting/initializing Apollo Client
- Update home, events and about page to opt in for SSG
- Removed MyApp.getIntialProps as it will stop the Auto Static
  optimization. Ref:
  (https://nextjs.org/docs/api-reference/data-fetching/getInitialProps#caveats)
- Handle the auth loading client side before checking of authentication

Co-authored-by: Aman Singh <aman.singh@thinkmill.com.au>
  • Loading branch information
singhArmani and Aman Singh authored Jul 7, 2020
1 parent e114894 commit caf3021
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 37 deletions.
11 changes: 11 additions & 0 deletions .changeset/light-llamas-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@keystonejs/demo-project-meetup': patch
---

Updated usage of Apollo based on Next.js [example](https://github.com/vercel/next.js/blob/canary/examples/with-apollo).

The **key changes** are:
- Less boilerplate code for setting/initializing Apollo Client
- Update home, events and about page to opt in for SSG
- Removed MyApp.getIntialProps as it will stop the [Auto Static optimization](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps#caveats).
- Handle the authentication in client-side only.
6 changes: 3 additions & 3 deletions demo-projects/meetup/site/components/Navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { jsx } from '@emotion/core';

import Link from 'next/link';
import { useAuth } from '../lib/authentication';
import { SignoutIcon } from '../primitives';
import { SignoutIcon, Loading } from '../primitives';
import { getForegroundColor, useLogoDimension } from '../helpers';
import { mq } from '../helpers/media';
import { fontSizes, gridSize, shadows } from '../theme';
Expand Down Expand Up @@ -143,7 +143,7 @@ const AnonActions = () => {
};

const Navbar = ({ background = 'white', ...props }) => {
const { isAuthenticated, user } = useAuth();
const { isAuthenticated, user, isLoading } = useAuth();
const { logoWidth, logoHeight, logoWidthSm, logoHeightSm } = useLogoDimension();
const foreground = getForegroundColor(background);

Expand Down Expand Up @@ -171,7 +171,7 @@ const Navbar = ({ background = 'white', ...props }) => {
<NavLink href="/about">About</NavLink>
<NavLink href="/events">Events</NavLink>
</div>
{isAuthenticated ? <UserActions user={user} /> : <AnonActions />}
{isLoading ? <Loading /> : isAuthenticated ? <UserActions user={user} /> : <AnonActions />}
</Header>
</ThemeContext.Provider>
);
Expand Down
42 changes: 42 additions & 0 deletions demo-projects/meetup/site/lib/apolloClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Derived from https://github.com/vercel/next.js/blob/canary/examples/with-apollo/lib/apolloClient.js
import { useMemo } from 'react';
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { createUploadLink } from 'apollo-upload-client';

let apolloClient;

function createApolloClient(req) {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: createUploadLink({
// TODO: server-side requests must have an absolute URI. We should find a way
// to make this part of the project config, seems highly opinionated here
uri: 'http://localhost:3000/admin/api',
credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
headers: req && req.headers,
}),
cache: new InMemoryCache(),
});
}

export function initializeApollo(initialState = null, req) {
const _apolloClient = apolloClient ?? createApolloClient(req);

// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// gets hydrated here
if (initialState) {
_apolloClient.cache.restore(initialState);
}
// 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 useApollo(initialState) {
const store = useMemo(() => initializeApollo(initialState), [initialState]);
return store;
}
37 changes: 6 additions & 31 deletions demo-projects/meetup/site/pages/_app.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import React from 'react';
import Head from 'next/head';
import gql from 'graphql-tag';
import { ApolloProvider } from '@apollo/react-hooks';
import { ToastProvider } from 'react-toast-notifications';

import withApollo from '../lib/withApollo';
import { AuthProvider } from '../lib/authentication';
import StylesBase from '../primitives/StylesBase';
import GoogleAnalytics from '../components/GoogleAnalytics';

const MyApp = ({ Component, pageProps, apolloClient, user }) => {
import { useApollo } from '../lib/apolloClient';
import { ApolloProvider } from '@apollo/react-hooks';
const MyApp = ({ Component, pageProps }) => {
const apolloClient = useApollo(pageProps.initialApolloState);
return (
<ToastProvider>
<ApolloProvider client={apolloClient}>
<AuthProvider initialUserValue={user}>
<AuthProvider>
<Head>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<meta
Expand All @@ -30,27 +28,4 @@ const MyApp = ({ Component, pageProps, apolloClient, user }) => {
);
};

MyApp.getInitialProps = async ({ Component, ctx }) => {
let pageProps = {};

const data = await ctx.apolloClient.query({
query: gql`
query {
authenticatedUser {
id
name
isAdmin
}
}
`,
fetchPolicy: 'network-only',
});

if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}

return { pageProps, user: data.data ? data.data.authenticatedUser : undefined };
};

export default withApollo(MyApp);
export default MyApp;
16 changes: 16 additions & 0 deletions demo-projects/meetup/site/pages/about.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Meta from '../components/Meta';
import { colors, gridSize } from '../theme';
import { GET_ORGANISERS } from '../graphql/organisers';
import { mq } from '../helpers/media';
import { initializeApollo } from '../lib/apolloClient';

const { publicRuntimeConfig } = getConfig();

Expand Down Expand Up @@ -121,3 +122,18 @@ const Organiser = ({ organiser }) => (
</li>
);
const Content = props => <div css={{ maxWidth: 720 }} {...props} />;

export async function getStaticProps() {
const apolloClient = initializeApollo();

await apolloClient.query({
query: GET_ORGANISERS,
});

return {
props: {
initialApolloState: apolloClient.cache.extract(),
},
unstable_revalidate: 1,
};
}
15 changes: 15 additions & 0 deletions demo-projects/meetup/site/pages/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Navbar from '../components/Navbar';
import Footer from '../components/Footer';
import Meta from '../components/Meta';
import { gridSize } from '../theme';
import { initializeApollo } from '../lib/apolloClient';

import { GET_ALL_EVENTS } from '../graphql/events';

Expand Down Expand Up @@ -38,3 +39,17 @@ export default function Events() {
</>
);
}
export async function getStaticProps() {
const apolloClient = initializeApollo();

await apolloClient.query({
query: GET_ALL_EVENTS,
});

return {
props: {
initialApolloState: apolloClient.cache.extract(),
},
unstable_revalidate: 1,
};
}
21 changes: 18 additions & 3 deletions demo-projects/meetup/site/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Meta from '../components/Meta';
import { GET_CURRENT_EVENTS } from '../graphql/events';
import { GET_EVENT_RSVPS } from '../graphql/rsvps';
import { GET_SPONSORS } from '../graphql/sponsors';
import { initializeApollo } from '../lib/apolloClient';

import Talks from '../components/Talks';
import Rsvp from '../components/Rsvp';
Expand Down Expand Up @@ -328,9 +329,23 @@ const Home = ({ now }) => {
);
};

Home.getInitialProps = async () => ({
now: new Date().toISOString(),
});
export async function getStaticProps() {
const apolloClient = initializeApollo();

const now = new Date().toISOString();
await apolloClient.query({
query: GET_CURRENT_EVENTS,
variables: { now },
});

return {
props: {
initialApolloState: apolloClient.cache.extract(),
now,
},
unstable_revalidate: 1,
};
}

export default Home;

Expand Down

0 comments on commit caf3021

Please sign in to comment.