Skip to content

Instantly share code, notes, and snippets.

@robabby
Created June 15, 2020 20:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robabby/4c33ef0ecb8b6d9871dbf2c2d70d752a to your computer and use it in GitHub Desktop.
Save robabby/4c33ef0ecb8b6d9871dbf2c2d70d752a to your computer and use it in GitHub Desktop.
Apollo Client Examples
import { typeDefs } from "./schema/resolvers";
import { ApolloClient } from "apollo-client";
import { ApolloLink } from "apollo-link";
import { ApolloProvider } from '@apollo/react-hooks';
import App from "./App";
import { InMemoryCache } from "apollo-cache-inmemory";
import React from "react";
import { createUploadLink } from "apollo-upload-client";
import { getToken } from "./utils/cookies";
import initialQuery from "./schema/queries/isLoggedIn";
import { setContext } from "apollo-link-context";
const token = getToken();
const httpUploadLink = createUploadLink({
uri: `${process.env.REACT_APP_API}/graphql`
});
const authLink = setContext((_, { headers }) => {
return {
headers: {
...headers,
Authorization: !!token ? `Bearer ${token}` : "",
"client-name": "Sherpa [web]",
credentials: "include"
}
};
});
const link = ApolloLink.from([authLink, httpUploadLink]);
const cache = new InMemoryCache({
dataIdFromObject: (o) => o.id
});
const client = new ApolloClient({
cache,
link,
typeDefs
});
client.writeData({
data: {
isLoggedIn: !!token
},
});
async function writeInitialQuery() {
const token = getToken();
return client.writeQuery({
query: initialQuery,
data: {
isLoggedIn: !!token
}
})
}
writeInitialQuery();
client.onResetStore(writeInitialQuery);
const Root = (props) => {
return (
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);
};
export default Root;
import React from "react";
import Head from "next/head";
import { ApolloProvider } from "@apollo/react-hooks";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import fetch from "isomorphic-unfetch";
let apolloClient = null;
function createIsomorphLink() {
const { createUploadLink } = require("apollo-upload-client");
return createUploadLink({
uri: process.env.GRAPHQL_URI,
credentials: "same-origin"
});
}
/**
* Creates and configures the ApolloClient
* @param {Object} [initialState={}]
*/
function createApolloClient(initialState = {}) {
const ssrMode = typeof window === "undefined";
const cache = new InMemoryCache({
dataIdFromObject: o => o.id
}).restore(initialState);
return new ApolloClient({
ssrMode,
link: createIsomorphLink() as any,
cache
});
}
/**
* 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 (typeof window === "undefined") {
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]
* @param {Boolean} [config.ssr=true]
*/
export function withApollo(PageComponent, { ssr = true } = {}) {
const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
const client = apolloClient || initApolloClient(apolloState);
return (
<ApolloProvider client={client}>
<PageComponent {...pageProps} />
</ApolloProvider>
);
};
// Set the correct displayName in development
if (process.env.NODE_ENV !== "production") {
const displayName =
PageComponent.displayName || PageComponent.name || "Component";
if (displayName === "App") {
console.warn("This withApollo HOC only works with PageComponents.");
}
WithApollo.displayName = `withApollo(${displayName})`;
}
if (ssr || PageComponent.getInitialProps) {
WithApollo.getInitialProps = async ctx => {
const { AppTree } = ctx;
// Initialize ApolloClient, add it to the ctx object so
// we can use it in `PageComponent.getInitialProp`.
const apolloClient = (ctx.apolloClient = initApolloClient());
// Run wrapped getInitialProps methods
let pageProps = {};
if (PageComponent.getInitialProps) {
pageProps = await PageComponent.getInitialProps(ctx);
}
// Only on the server:
if (typeof window === "undefined") {
// When redirecting, the response is finished.
// No point in continuing to render
if (ctx.res && ctx.res.finished) {
return pageProps;
}
// Only if ssr is enabled
if (ssr) {
try {
// Run all GraphQL queries
const { getDataFromTree } = await import("@apollo/react-ssr");
await getDataFromTree(
<AppTree
pageProps={{
...pageProps,
apolloClient
}}
/>
);
} catch (error) {
// Prevent Apollo Client GraphQL errors from crashing SSR.
// Handle them in components via the data.error prop:
// https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
console.error("Error while running `getDataFromTree`", error);
}
// getDataFromTree does not call componentWillUnmount
// head side effect therefore need to be cleared manually
Head.rewind();
}
}
// Extract query data from the Apollo store
const apolloState = apolloClient.cache.extract();
return {
...pageProps,
apolloState
};
};
}
return WithApollo;
}
import { ApolloClient } from "apollo-client";
import { ApolloLink } from "apollo-link";
import { InMemoryCache } from "apollo-cache-inmemory";
import { createUploadLink } from "apollo-upload-client";
import { getUserIdFromToken } from "../utils/getUserId";
import initialQuery from "./queries/isLoggedIn";
import { useMemo } from "react";
let apolloClient;
function createApolloClient(initialState) {
const cache = new InMemoryCache({
dataIdFromObject: o => o.id
});
const { isLoggedIn, token } = initialState;
const initialData = {
id: getUserIdFromToken(token),
isLoggedIn,
token
};
cache.writeData({ data: initialData });
const httpUploadLink = createUploadLink({
uri: process.env.GRAPHQL_URI
});
const link = new ApolloLink((operation, forward) => {
operation.setContext({
credentials: "same-origin",
headers: {
"Access-Control-Allow-Origin": "*",
Authorization: token ? `Bearer ${token}` : ""
}
});
return forward(operation);
}).concat(httpUploadLink);
const client = new ApolloClient({
cache,
link,
resolvers: {},
ssrMode: typeof window === "undefined"
});
client.writeData({
data: initialData
});
async function writeInitialQuery() {
return client.writeQuery({
query: initialQuery,
data: initialData
});
}
writeInitialQuery();
client.onResetStore(writeInitialQuery);
return client;
}
export function initializeApollo(initialState) {
const _apolloClient = apolloClient ?? createApolloClient(initialState);
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// gets hydrated here
if (initialState) {
console.log("initializeApollo - initialState: ", 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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment