Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ssrMode #8709

Merged
merged 2 commits into from Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -10,6 +10,9 @@
- Fix ObservableQuery.getCurrentResult() returning cached data with certain fetch policies. <br/>
[@brainkim](https://github.com/brainkim) in [#8718](https://github.com/apollographql/apollo-client/pull/8718)

- Prevent `ssrMode`/`ssrForceFetchDelay` from causing queries to hang. <br/>
[@brainkim](https://github.com/brainkim) in [#8709](https://github.com/apollographql/apollo-client/pull/8709)


## Apollo Client 3.4.9

Expand Down
6 changes: 1 addition & 5 deletions src/react/data/QueryData.ts
Expand Up @@ -101,11 +101,7 @@ export class QueryData<TData, TVariables> extends OperationData<
public afterExecute({ lazy = false }: { lazy?: boolean } = {}) {
this.isMounted = true;
const options = this.getOptions();
if (
this.currentObservable &&
!this.ssrInitiated() &&
!this.client.disableNetworkFetches
) {
if (this.currentObservable && !this.ssrInitiated()) {
this.startQuerySubscription();
}

Expand Down
68 changes: 68 additions & 0 deletions src/react/hooks/__tests__/useQuery.test.tsx
Expand Up @@ -557,6 +557,74 @@ describe('useQuery Hook', () => {
expect(result.current.loading).toBe(false);
expect(result.current.data).toEqual({ hello: 'from link' });
});

it('should use the cache when in ssrMode and fetchPolicy is `network-only`', async () => {
const query = gql`query { hello }`;
const link = mockSingleLink(
{
request: { query },
result: { data: { hello: 'from link' } },
},
);

const cache = new InMemoryCache();
cache.writeQuery({
query,
data: { hello: 'from cache' },
});

const client = new ApolloClient({ link, cache, ssrMode: true, });
const { result, waitForNextUpdate } = renderHook(
() => useQuery(query, { fetchPolicy: 'network-only' }),
{
wrapper: ({ children }) => (
<ApolloProvider client={client}>
{children}
</ApolloProvider>
),
},
);

expect(result.current.loading).toBe(false);
expect(result.current.data).toEqual({ hello: 'from cache' });

await expect(waitForNextUpdate({ timeout: 20 }))
.rejects.toThrow('Timed out');
});

it('should not hang when ssrMode is true but the cache is not populated for some reason', async () => {
const query = gql`query { hello }`;
const link = mockSingleLink(
{
request: { query },
result: { data: { hello: 'from link' } },
},
);

const client = new ApolloClient({
link,
cache: new InMemoryCache(),
ssrMode: true,
});
const { result, waitForNextUpdate } = renderHook(
() => useQuery(query),
{
wrapper: ({ children }) => (
<ApolloProvider client={client}>
{children}
</ApolloProvider>
),
},
);

expect(result.current.loading).toBe(true);
expect(result.current.data).toBe(undefined);

await waitForNextUpdate();

expect(result.current.loading).toBe(false);
expect(result.current.data).toEqual({ hello: 'from link' });
});
});

describe('polling', () => {
Expand Down
28 changes: 8 additions & 20 deletions src/react/ssr/__tests__/useQuery.test.tsx
Expand Up @@ -6,7 +6,6 @@ import { ApolloClient } from '../../../core';
import { InMemoryCache } from '../../../cache';
import { ApolloProvider } from '../../context';
import { useApolloClient, useQuery } from '../../hooks';
import { render, wait } from '@testing-library/react';
import { renderToStringWithData } from '..';

describe('useQuery Hook SSR', () => {
Expand Down Expand Up @@ -109,9 +108,7 @@ describe('useQuery Hook SSR', () => {
});
});

it(
'should skip both SSR tree rendering and SSR component rendering if ' +
'`ssr` option is `false` and `ssrMode` is `true`',
it('should skip both SSR tree rendering and SSR component rendering if `ssr` option is `false` and `ssrMode` is `true`',
async () => {
const link = mockSingleLink({
request: { query: CAR_QUERY },
Expand All @@ -136,6 +133,7 @@ describe('useQuery Hook SSR', () => {
break;
case 1: // FAIL; should not render a second time
default:
throw new Error("Duplicate render");
}

renderCount += 1;
Expand All @@ -148,22 +146,12 @@ describe('useQuery Hook SSR', () => {
</ApolloProvider>
);

await renderToStringWithData(app).then(result => {
expect(renderCount).toBe(1);
expect(result).toEqual('');
});

renderCount = 0;

render(
<ApolloProvider client={client}>
<Component />
</ApolloProvider>
);

await wait(() => {
expect(renderCount).toBe(1);
});
const result = await renderToStringWithData(app);
expect(renderCount).toBe(1);
expect(result).toEqual('');
await new Promise((resolve) => setTimeout(resolve, 20));
expect(renderCount).toBe(1);
expect(result).toEqual('');
}
);

Expand Down