@apollo/client
是一个用于与 GraphQL 后端进行交互的库,提供了简洁的 API 和强大的功能,帮助开发者在 React 等前端框架中轻松实现数据查询、缓存管理和状态管理。
1. layout使用 @apollo/client provider
tsx
//[locale]/layout.tsx
import { ApolloWrapper } from '@/lib/ApolloProvider'
//... ohter code
export default async function LocaleLayout({ children, params }: Props) {
return (
<html lang={locale} suppressHydrationWarning>
<body>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<NextIntlClientProvider>
<ApolloWrapper>{children}</ApolloWrapper>
<Toaster />
</NextIntlClientProvider>
</ThemeProvider>
</body>
</html>
)
}
2. 定义 ApolloWrapper 组件
tsx
'use client'
import type React from 'react'
import {
ApolloClient,
ApolloProvider,
InMemoryCache,
HttpLink,
} from '@apollo/client'
import { useMemo } from 'react'
// Function to create a new Apollo Client instance
function createApolloClient() {
return new ApolloClient({
cache: new InMemoryCache({}),
link: new HttpLink({
uri: '/api/graphql',
// You can add additional options here like headers, credentials, etc.
}),
defaultOptions: {
watchQuery: {
fetchPolicy: 'cache-and-network',
},
},
})
}
// Provider component that wraps your app and makes Apollo Client available
export function ApolloWrapper({ children }: { children: React.ReactNode }) {
const client = useMemo(() => createApolloClient(), [])
return <ApolloProvider client={client}>{children}</ApolloProvider>
}
3. 查询单个文章
在客户端组件中可以使用 useQuery
获取数据, 或者 useApolloClient()
来获取 apolloClient
,再用 apolloClient.query()
来查询数据
tsx
import { gql, useMutation, useQuery } from '@apollo/client'
//...
const GET_POST = gql`
query GetPost($id: ID!) {
post(id: $id) {
id
title
summary
content
}
}
`
const id = searchParams.get('id')
const {
data: postDsata1,
loading,
error,
} = useQuery(GET_POST, {
variables: {
id,
},
})
const { data: postData2 } = await apolloClient.query({
query: GET_POST,
variables: {
id,
},
})
4. 在服务端组件使用 apolloClient
定义服务端 apolloClient 实例
tsx
// lib/apolloServerClient.ts
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client'
export function getApolloServerClient() {
const httpLink = new HttpLink({
uri: process.env.GRAPHQL_ENDPOINT || 'http://localhost:3000/api/graphql',
})
return new ApolloClient({
cache: new InMemoryCache(),
link: httpLink,
// Important for SSR to avoid leaking data between requests
ssrMode: true,
})
}
在服务端组件中使用,例如文章详情 page.tsx
Next.js构建时会优先静态渲染,这里我们强制设置使用动态渲染 export const dynamic = 'force-dynamic'
,每次都拿最新的数据 export const revalidate = 0
tsx
import { getApolloServerClient } from '@/lib/apolloServerClient'
import { gql } from '@apollo/client'
import { format } from 'date-fns'
import { Locale } from 'next-intl'
import { setRequestLocale } from 'next-intl/server'
export const dynamic = 'force-dynamic'
export const revalidate = 0
type Props = {
params: Promise<{ locale: Locale; id: string }>
}
export default async function PagePostsDetail({ params }: Props) {
const { locale, id } = await params
setRequestLocale(locale)
const { data } = await getApolloServerClient().query({
query: gql`
query GetPost($id: ID!, $userId: ID) {
post(id: $id) {
id
title
summary
content
createdAt
updatedAt
createdBy {
id
nickname
}
}
}
`,
variables: {
id,
},
})
return (
<div className="page-wrapper py-6">
<div className="">
<div key={data.post.id} className="relative flex flex-col gap-4">
<div className="text-xl font-bold">{data.post.title}</div>
<div className="text-muted-foreground flex items-center gap-2 text-sm">
<span>{data.post.createdBy.nickname}</span>
<span>{format(data.post.createdAt, 'yyyy.MM.dd HH:mm')}</span>
</div>
</div>
</div>
)
}