Skip to content

Commit

Permalink
feat: implement SSR (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
avocadowastaken authored and trojanowski committed Jan 8, 2019
1 parent 873e7de commit 664edc2
Show file tree
Hide file tree
Showing 12 changed files with 553 additions and 19 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"@types/jest": "^23.3.10",
"@types/lodash": "^4.14.119",
"@types/react": "^16.7.17",
"@types/react-dom": "^16.0.11",
"apollo-cache-inmemory": "^1.3.11",
"apollo-client": "^2.4.7",
"apollo-link": "^1.2.4",
Expand All @@ -99,8 +100,8 @@
"jest-react-profiler": "^0.1.3",
"lint-staged": "^8.1.0",
"prettier": "^1.15.2",
"react": "^16.7.0-alpha.2",
"react-dom": "^16.7.0-alpha.2",
"react": "16.7.0-alpha.2",
"react-dom": "16.7.0-alpha.2",
"react-testing-library": "^5.3.1",
"rimraf": "^2.6.2",
"standard-version": "^4.4.0",
Expand Down
12 changes: 12 additions & 0 deletions src/SuspenseSSR.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { Suspense, SuspenseProps, useContext } from 'react';
import { SSRContext } from './internal/SSRContext';

export function unstable_SuspenseSSR({ children, fallback }: SuspenseProps) {
const ssrManager = useContext(SSRContext);

return ssrManager ? (
<>{children}</>
) : (
<Suspense fallback={fallback}>{children}</Suspense>
);
}
110 changes: 110 additions & 0 deletions src/__tests__/SuspenseSSR-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import ApolloClient from 'apollo-client';
import { ApolloLink } from 'apollo-link';
import { MockedResponse } from 'apollo-link-mock';
import gql from 'graphql-tag';
import * as React from 'react';
import { renderToString } from 'react-dom/server';
import { render } from 'react-testing-library';

import { ApolloProvider } from '../ApolloContext';
import { unstable_SuspenseSSR as SuspenseSSR } from '../SuspenseSSR';
import createClient from '../__testutils__/createClient';
import flushEffectsAndWait from '../__testutils__/flushEffectsAndWait';
import { getMarkupFromTree } from '../getMarkupFromTree';
import { QueryHookOptions, useQuery } from '../useQuery';

const USER_QUERY = gql`
{
currentUser {
firstName
}
}
`;

interface UserQueryResult {
currentUser: { firstName: string };
}

const MOCKS: MockedResponse[] = [
{
request: { query: USER_QUERY },
result: { data: { currentUser: { firstName: 'James' } } },
},
];

function createMockClient(link?: ApolloLink) {
return createClient({ link, mocks: MOCKS, addTypename: false });
}

function UserDetails(props: QueryHookOptions<{}>) {
const { data, loading } = useQuery<UserQueryResult>(USER_QUERY, props);

return (
<>
{loading
? 'Loading'
: !data
? 'No Data'
: !data.currentUser
? 'No Current User'
: data.currentUser.firstName}
</>
);
}

interface UserWrapperProps extends QueryHookOptions<{}> {
readonly client: ApolloClient<object>;
}

function UserDetailsWrapper({ client, ...props }: UserWrapperProps) {
return (
<ApolloProvider client={client}>
<SuspenseSSR fallback={<>Loading with suspense</>}>
<UserDetails {...props} />
</SuspenseSSR>
</ApolloProvider>
);
}

describe.each([[true], [false]])('SuspenseSSR with "suspend: %s"', suspend => {
it('not throws in react-dom', async () => {
const client = createMockClient();

const { container } = render(
<UserDetailsWrapper client={client} suspend={suspend} />
);

if (suspend) {
expect(container).toMatchInlineSnapshot(`
<div>
Loading with suspense
</div>
`);
} else {
expect(container).toMatchInlineSnapshot(`
<div>
Loading
</div>
`);
}

await flushEffectsAndWait();

expect(container).toMatchInlineSnapshot(`
<div>
James
</div>
`);
});

it('not throws in react-dom/server', async () => {
const client = createMockClient();

await expect(
getMarkupFromTree({
renderFunction: renderToString,
tree: <UserDetailsWrapper client={client} suspend={suspend} />,
})
).resolves.toMatchInlineSnapshot(`"James"`);
});
});
Loading

0 comments on commit 664edc2

Please sign in to comment.