Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
Fix cache-less queries in SSR (#770)
Browse files Browse the repository at this point in the history
  • Loading branch information
lemonmade authored Jul 5, 2019
1 parent e2e682a commit 49c3cdd
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 4 deletions.
12 changes: 8 additions & 4 deletions packages/react-graphql/src/hooks/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ export default function useQuery<
} = options;
const client = useApolloClient(overrideClient);

if (typeof window === 'undefined' && skip) {
return createDefaultResult(client, variables);
if (typeof window === 'undefined' && (skip || fetchPolicy === 'no-cache')) {
return {...createDefaultResult(client, variables), loading: !skip};
}

const query = useGraphQLDocument(queryOrComponent);

const normalizedFetchPolicy =
typeof window === 'undefined' && fetchPolicy === 'network-only'
? 'cache-first'
: fetchPolicy;
const serializedVariables = variables && JSON.stringify(variables);
const watchQueryOptions = useMemo<WatchQueryOptions<Variables> | null>(
() => {
Expand All @@ -55,7 +59,7 @@ export default function useQuery<
query,
context,
variables,
fetchPolicy,
fetchPolicy: normalizedFetchPolicy,
errorPolicy,
pollInterval,
notifyOnNetworkStatusChange,
Expand All @@ -67,7 +71,7 @@ export default function useQuery<
// eslint-disable-next-line react-hooks/exhaustive-deps
context && JSON.stringify(context),
serializedVariables,
fetchPolicy,
normalizedFetchPolicy,
errorPolicy,
pollInterval,
notifyOnNetworkStatusChange,
Expand Down
82 changes: 82 additions & 0 deletions packages/react-graphql/src/hooks/tests/query-ssr.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* @jest-environment node
*/

import React from 'react';
import {renderToString} from 'react-dom/server';
import gql from 'graphql-tag';
import {FetchPolicy} from 'apollo-client';
import {createGraphQLFactory} from '@shopify/graphql-testing';
import {extract} from '@shopify/react-effect/server';

import useQuery from '../query';
import {ApolloProvider} from '../../ApolloProvider';

const petQuery = gql`
query PetQuery {
pets {
name
}
}
`;

const createGraphQL = createGraphQLFactory();
const mockData = {
pets: [
{
__typename: 'Cat',
name: 'Garfield',
},
],
};

function MockQuery({fetchPolicy = 'network-only' as FetchPolicy}) {
const {data, loading} = useQuery(petQuery, {fetchPolicy});
return loading ? <div>loading</div> : <pre>{JSON.stringify(data)}</pre>;
}

describe('useQuery', () => {
it('does not loop infinitely when a query has network-only during SSR', async () => {
const graphQL = createGraphQL({PetQuery: mockData});
const afterEachSpy = jest.fn();

const extractPromise = extract(
<ApolloProvider client={graphQL.client}>
<MockQuery fetchPolicy="network-only" />
</ApolloProvider>,
{
afterEachPass: afterEachSpy,
},
);

await graphQL.resolveAll();
await extractPromise;

// One call for the first pass, another call after the GraphQL
// resolves
expect(afterEachSpy).toHaveBeenCalledTimes(2);
});

it('does not run a query with the no-cache fetch policy during SSR', async () => {
const graphQL = createGraphQL({PetQuery: mockData});
const afterEachSpy = jest.fn();
const element = (
<ApolloProvider client={graphQL.client}>
<MockQuery fetchPolicy="no-cache" />
</ApolloProvider>
);

const extractPromise = extract(element, {
afterEachPass: afterEachSpy,
});

await graphQL.resolveAll();
await extractPromise;

// One call for the first pass, which is the only one because there are
// no GraphQL queries to resolve.
expect(afterEachSpy).toHaveBeenCalledTimes(1);

expect(renderToString(element)).toContain('loading');
});
});

0 comments on commit 49c3cdd

Please sign in to comment.