(query);
24 |
25 | return (
26 |
27 |
28 |
{count}
29 |
30 |
36 |
37 |
38 |
39 | {error ? (
40 | Oh no, there was an error
41 | ) : data ? (
42 |
49 | {data?.users.map((user) => (
50 |
54 |

59 |
{user.name}
60 |
61 | ))}
62 |
63 | ) : null}
64 |
65 | );
66 | }
67 |
--------------------------------------------------------------------------------
/src/app/client-side/loading.tsx:
--------------------------------------------------------------------------------
1 | export default function Loading() {
2 | return Loading...
;
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/client-side/page.tsx:
--------------------------------------------------------------------------------
1 | import ListUsers from "./listusers";
2 |
3 | export const dynamic = "force-dynamic";
4 |
5 | export default function ClientSide() {
6 | return ;
7 | }
8 |
--------------------------------------------------------------------------------
/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wpcodevo/nextjs13-apollo-client/7aeb3fad504c4e789399ac33f1bb4c13bf19724f/src/app/favicon.ico
--------------------------------------------------------------------------------
/src/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | :root {
6 | --foreground-rgb: 0, 0, 0;
7 | --background-start-rgb: 214, 219, 220;
8 | --background-end-rgb: 255, 255, 255;
9 | }
10 |
11 | @media (prefers-color-scheme: dark) {
12 | :root {
13 | --foreground-rgb: 255, 255, 255;
14 | --background-start-rgb: 0, 0, 0;
15 | --background-end-rgb: 0, 0, 0;
16 | }
17 | }
18 |
19 | body {
20 | color: rgb(var(--foreground-rgb));
21 | background: linear-gradient(
22 | to bottom,
23 | transparent,
24 | rgb(var(--background-end-rgb))
25 | )
26 | rgb(var(--background-start-rgb));
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import { ApolloWrapper } from "@/lib/apollo-wrapper";
2 | // import "./globals.css";
3 |
4 | export const metadata = {
5 | title: "Create Next App",
6 | description: "Generated by create next app",
7 | };
8 |
9 | export default function RootLayout({
10 | children,
11 | }: {
12 | children: React.ReactNode;
13 | }) {
14 | return (
15 |
16 |
17 | {children}
18 |
19 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 |
3 | export default function Home() {
4 | return (
5 | <>
6 | Hello, Next.js 13 App Directory!
7 |
8 |
9 | Use Apollo Client inside Client Side Component
10 |
11 |
12 |
13 |
14 | Use Apollo Client inside React Server Component (RSC)
15 |
16 |
17 | >
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/server-side/loading.tsx:
--------------------------------------------------------------------------------
1 | export default function Loading() {
2 | return Loading...
;
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/server-side/page.tsx:
--------------------------------------------------------------------------------
1 | import { getClient } from "@/lib/client";
2 | import { gql } from "@apollo/client";
3 | import React from "react";
4 |
5 | export const dynamic = "force-dynamic";
6 |
7 | const query = gql`
8 | query {
9 | users {
10 | id
11 | name
12 | email
13 | }
14 | }
15 | `;
16 |
17 | interface Response {
18 | users: { id: number; name: string; email: string }[];
19 | }
20 |
21 | export default async function ServerSide() {
22 | const data = await getClient().query({
23 | query,
24 | });
25 |
26 | return (
27 |
28 |
35 | {data.data.users.map((user) => (
36 |
40 |

45 |
{user.name}
46 |
47 | ))}
48 |
49 |
50 | );
51 | }
52 |
--------------------------------------------------------------------------------
/src/lib/apollo-wrapper.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import {
4 | ApolloClient,
5 | ApolloLink,
6 | HttpLink,
7 | SuspenseCache,
8 | } from "@apollo/client";
9 | import {
10 | ApolloNextAppProvider,
11 | NextSSRInMemoryCache,
12 | SSRMultipartLink,
13 | } from "@apollo/experimental-nextjs-app-support/ssr";
14 |
15 | const GRAPHQL_ENDPOINT =
16 | process.env.GRAPHQL_ENDPOINT || "https://jsonplaceholder.ir/graphql";
17 |
18 | function makeClient() {
19 | const httpLink = new HttpLink({
20 | uri: GRAPHQL_ENDPOINT,
21 | });
22 |
23 | return new ApolloClient({
24 | cache: new NextSSRInMemoryCache(),
25 | link:
26 | typeof window === "undefined"
27 | ? ApolloLink.from([
28 | // in a SSR environment, if you use multipart features like
29 | // @defer, you need to decide how to handle these.
30 | // This strips all interfaces with a `@defer` directive from your queries.
31 | new SSRMultipartLink({
32 | stripDefer: true,
33 | }),
34 | httpLink,
35 | ])
36 | : httpLink,
37 | });
38 | }
39 |
40 | function makeSuspenseCache() {
41 | return new SuspenseCache();
42 | }
43 |
44 | export function ApolloWrapper({ children }: React.PropsWithChildren) {
45 | return (
46 |
50 | {children}
51 |
52 | );
53 | }
54 |
--------------------------------------------------------------------------------
/src/lib/client.ts:
--------------------------------------------------------------------------------
1 | import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";
2 | import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc";
3 |
4 | const GRAPHQL_ENDPOINT =
5 | process.env.GRAPHQL_ENDPOINT || "https://jsonplaceholder.ir/graphql";
6 |
7 | export const { getClient } = registerApolloClient(() => {
8 | return new ApolloClient({
9 | cache: new InMemoryCache(),
10 | link: new HttpLink({
11 | uri: GRAPHQL_ENDPOINT,
12 | }),
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
5 | './src/components/**/*.{js,ts,jsx,tsx,mdx}',
6 | './src/app/**/*.{js,ts,jsx,tsx,mdx}',
7 | ],
8 | theme: {
9 | extend: {
10 | backgroundImage: {
11 | 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
12 | 'gradient-conic':
13 | 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
14 | },
15 | },
16 | },
17 | plugins: [],
18 | }
19 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "plugins": [
18 | {
19 | "name": "next"
20 | }
21 | ],
22 | "paths": {
23 | "@/*": ["./src/*"]
24 | }
25 | },
26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
27 | "exclude": ["node_modules"]
28 | }
29 |
--------------------------------------------------------------------------------