Skip to content

Commit

Permalink
Adds support for useBackgroundQuery and useReadQuery in Streaming…
Browse files Browse the repository at this point in the history
… SSR (#38)
  • Loading branch information
alessbell authored Jun 23, 2023
1 parent 5bdbce6 commit 471404e
Show file tree
Hide file tree
Showing 24 changed files with 303 additions and 88 deletions.
10 changes: 3 additions & 7 deletions examples/app-dir-experiments/app/ssr/ApolloWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
"use client";

import {
ApolloClient,
ApolloLink,
HttpLink,
SuspenseCache,
} from "@apollo/client";
import { ApolloLink, HttpLink, SuspenseCache } from "@apollo/client";
import {
ApolloNextAppProvider,
NextSSRInMemoryCache,
NextSSRApolloClient,
SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";
import { setVerbosity } from "ts-invariant";
Expand All @@ -21,7 +17,7 @@ function makeClient() {
fetchOptions: { cache: "no-store" },
});

return new ApolloClient({
return new NextSSRApolloClient({
cache: new NextSSRInMemoryCache(),
link:
typeof window === "undefined"
Expand Down
2 changes: 1 addition & 1 deletion examples/app-dir-experiments/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"lint": "next lint"
},
"dependencies": {
"@apollo/client": ">=3.8.0-beta.2",
"@apollo/client": ">=3.8.0-beta.4",
"@apollo/experimental-nextjs-app-support": "workspace:^",
"@apollo/server": "^4.6.0",
"@as-integrations/next": "^1.3.0",
Expand Down
10 changes: 3 additions & 7 deletions examples/hack-the-supergraph-ssr/app/ApolloWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
"use client";
import React from "react";
import {
ApolloClient,
ApolloLink,
HttpLink,
SuspenseCache,
} from "@apollo/client";
import { ApolloLink, HttpLink, SuspenseCache } from "@apollo/client";
import clientCookies from "js-cookie";
import {
ApolloNextAppProvider,
NextSSRInMemoryCache,
NextSSRApolloClient,
SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";

Expand Down Expand Up @@ -75,7 +71,7 @@ export function ApolloWrapper({
])
: ApolloLink.from([delayLink, httpLink]);

return new ApolloClient({
return new NextSSRApolloClient({
cache: new NextSSRInMemoryCache(),
link,
});
Expand Down
15 changes: 6 additions & 9 deletions examples/hack-the-supergraph-ssr/app/error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import React from "react";
import { Box, Heading, Text, VStack } from "@chakra-ui/react";

export const Error = ({
children,
code,
error,
}: React.PropsWithChildren<{
code?: string;
error: { toString(): string };
}>) => (
reset,
}: {
error: Error;
reset: () => void;
}) => (
<VStack spacing="12">
<VStack textAlign="center">
<Heading size="4xl">{code ?? "Unknown Error"}</Heading>
<Heading fontSize="3xl">Houston, something went wrong on our end</Heading>
<Text>Please review the information below for more details.</Text>
</VStack>
Expand All @@ -25,10 +23,9 @@ export const Error = ({
borderRadius="8px"
borderColor="brand.light"
>
<Text color="brand.error">{error.toString()}</Text>
<Text color="brand.error">Error: {error.message}</Text>
</Box>
)}
{children}
</VStack>
);

Expand Down
2 changes: 1 addition & 1 deletion examples/hack-the-supergraph-ssr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"lint": "next lint"
},
"dependencies": {
"@apollo/client": ">=3.8.0-beta.2",
"@apollo/client": ">=3.8.0-beta.4",
"@apollo/experimental-nextjs-app-support": "workspace:^",
"@apollo/space-kit": "^9.11.0",
"@chakra-ui/next-js": "^2.1.2",
Expand Down
10 changes: 3 additions & 7 deletions examples/polls-demo/app/cc/apollo-wrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
"use client";

import { ApolloLink, HttpLink, SuspenseCache } from "@apollo/client";
import {
ApolloClient,
ApolloLink,
HttpLink,
SuspenseCache,
} from "@apollo/client";
import {
NextSSRApolloClient,
ApolloNextAppProvider,
NextSSRInMemoryCache,
SSRMultipartLink,
Expand All @@ -25,7 +21,7 @@ function makeClient() {
uri: "https://fragrant-shadow-9470.fly.dev/",
});

return new ApolloClient({
return new NextSSRApolloClient({
cache: new NextSSRInMemoryCache(),
link:
typeof window === "undefined"
Expand Down
10 changes: 8 additions & 2 deletions examples/polls-demo/app/cc/error.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
"use client";

export default function Error(error: { toString(): string }) {
return <p>Error: {error.toString()}</p>;
export default function Error({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return <p>Error: {error.message}</p>;
}
5 changes: 0 additions & 5 deletions examples/polls-demo/app/cc/loading.tsx

This file was deleted.

4 changes: 2 additions & 2 deletions examples/polls-demo/app/cc/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Poll } from "./poll-cc";
import { PollWrapper } from "./poll-cc";

export const dynamic = "force-dynamic";

export default async function Home() {
return <Poll />;
return <PollWrapper />;
}
25 changes: 19 additions & 6 deletions examples/polls-demo/app/cc/poll-cc.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
"use client";

import { useSuspenseQuery } from "@apollo/experimental-nextjs-app-support/ssr";
import { Suspense } from "react";
import {
useReadQuery,
useBackgroundQuery,
} from "@apollo/experimental-nextjs-app-support/ssr";
import { useMutation } from "@apollo/client";
import { QueryReference } from "@apollo/client/react/cache/QueryReference";
import { Poll as PollInner } from "@/components/poll";

import { useState, useCallback } from "react";

import {
AnswerPollDocument,
GetPollDocument,
GetPollQuery,
} from "@/components/poll/documents.generated";

export const Poll = () => {
const [showResults, setShowResults] = useState(false);

const { data } = useSuspenseQuery(GetPollDocument, {
export const PollWrapper = () => {
const [queryRef] = useBackgroundQuery(GetPollDocument, {
variables: { id: "1", delay: 0 },
});

return (
<Suspense fallback={<>Loading...</>}>
<Poll queryRef={queryRef} />
</Suspense>
);
};

const Poll = ({ queryRef }: { queryRef: QueryReference<GetPollQuery> }) => {
const { data } = useReadQuery(queryRef);
const [showResults, setShowResults] = useState(false);
const [mutate, { loading: mutationLoading }] =
useMutation(AnswerPollDocument);

Expand Down
2 changes: 1 addition & 1 deletion examples/polls-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"codegen": "graphql-codegen --config codegen.ts"
},
"dependencies": {
"@apollo/client": ">=3.8.0-beta.2",
"@apollo/client": ">=3.8.0-beta.4",
"@apollo/experimental-nextjs-app-support": "workspace:^",
"@apollo/server": "^4.7.0",
"@as-integrations/next": "^1.3.0",
Expand Down
6 changes: 6 additions & 0 deletions package/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,11 @@ module.exports = {
rules: {
"@typescript-eslint/no-explicit-any": "off",
"react/prop-types": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{
varsIgnorePattern: "^_",
},
],
},
};
11 changes: 8 additions & 3 deletions package/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ First, create a new file `app/ApolloWrapper.js`:
// ^ this file needs the "use client" pragma

import {
ApolloClient,
ApolloLink,
HttpLink,
SuspenseCache,
} from "@apollo/client";
import {
ApolloNextAppProvider,
NextSSRInMemoryCache,
NextSSRApolloClient,
SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";

Expand All @@ -103,7 +103,7 @@ function makeClient() {
fetchOptions: { cache: "no-store" },
});

return new ApolloClient({
return new NextSSRApolloClient({
// use the `NextSSRInMemoryCache`, not the normal `InMemoryCache`
cache: new NextSSRInMemoryCache(),
link:
Expand Down Expand Up @@ -164,7 +164,12 @@ export default function RootLayout({
> ☝️ This will work even if your layout is a React Server Component and will also allow the children of the layout to be React Server Components.
> It just makes sure that all Client Components will have access to the same Apollo Client instance, shared through the `ApolloNextAppProvider`.
Now you can use the hooks `useQuery`, `useSuspenseQuery`, `useFragment`, and `useApolloClient` from `"@apollo/experimental-nextjs-app-support/ssr"` in your Client components like you are used to.
You can import the following Apollo Client hooks from `"@apollo/experimental-nextjs-app-support/ssr"` in your client components (make sure you are not importing these hooks from `@apollo/client` as this package wraps and re-exports them to support streaming SSR):
- `useQuery`
- `useSuspenseQuery`
- `useBackgroundQuery`
- `useReadQuery`
- `useFragment`

If you want to make the most of the streaming SSR features offered by React & the Next.js App Router, consider using the [`useSuspenseQuery`](https://www.apollographql.com/docs/react/api/react/hooks-experimental/#using-usesuspensequery_experimental) and [`useFragment`](https://www.apollographql.com/docs/react/api/react/hooks-experimental/#using-usefragment_experimental) hooks.

Expand Down
4 changes: 2 additions & 2 deletions package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
},
"packageManager": "yarn@3.5.0",
"devDependencies": {
"@apollo/client": ">=3.8.0-beta.2",
"@apollo/client": ">=3.8.0-beta.4",
"@total-typescript/shoehorn": "^0.1.0",
"@tsconfig/recommended": "^1.0.1",
"@typescript-eslint/eslint-plugin": "latest",
Expand All @@ -59,7 +59,7 @@
"vitest": "^0.30.1"
},
"peerDependencies": {
"@apollo/client": ">=3.8.0-beta.2",
"@apollo/client": ">=3.8.0-beta.4",
"next": "^13.4.1",
"react": "^18"
},
Expand Down
10 changes: 9 additions & 1 deletion package/src/ssr/ApolloRehydrateSymbols.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { SuperJSONResult } from "superjson/dist/types";
import { RehydrationCache, ResultsCache } from "./types";
import {
RehydrationCache,
ResultsCache,
BackgroundQueriesCache,
} from "./types";
import type { DataTransport } from "./dataTransport";

declare global {
interface Window {
[ApolloRehydrationCache]?: RehydrationCache;
[ApolloResultCache]?: ResultsCache;
[ApolloSSRDataTransport]?: DataTransport<SuperJSONResult>;
[ApolloBackgroundQueryTransport]?: BackgroundQueriesCache;
}
}
export const ApolloRehydrationCache = Symbol.for("ApolloRehydrationCache");
export const ApolloResultCache = Symbol.for("ApolloResultCache");
export const ApolloSSRDataTransport = Symbol.for("ApolloSSRDataTransport");
export const ApolloBackgroundQueryTransport = Symbol.for(
"ApolloBackgroundQueryTransport"
);
Loading

0 comments on commit 471404e

Please sign in to comment.