SSR getServerSideProps 上的 Next.js graphql 上下文为空 {}

标签 next.js

我有带有 getServerSideProps 的页面:

export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const apolloClient = initializeApollo()

  await apolloClient.query({
    query: UserQuery,
    variables: { id: Number(ctx.query.id) },
  })

  return {
    props: { initialApolloState: apolloClient.cache.extract() },
  }
}
和用户的解析器:
resolve: async (_parent, { where }, ctx, info) => {
 const select = new PrismaSelect(info).value

 console.log(ctx) // {} why is empty when i use getServerSideProps?

 const res = await ctx.db.user.findOne({
    where: { id: 1 },
    ...select,
 })

 return null
},
相同的客户端查询工作正常,但出于某种原因,当我使用 getServerSideProps 时ctx 为空。如何解决这个问题?
我可以将 ctx 传递给 const apolloClient = initializeApollo(null, ctx) ,但它不会运行带有 db 属性的 apolloServer ctx 解析器函数,并且 ctx.db 将是未定义的。

阿波罗服务器:
const apolloServer = new ApolloServer({
  schema,
  async context(ctx: Ctx): Promise<Ctx> {
    ctx.db = prisma

    return ctx
  },
})

export const apolloServerHandler = apolloServer.createHandler({ path: '/api/graphql' })
Apollo-客户:
import { useMemo } from 'react'
import { ApolloClient, InMemoryCache, NormalizedCacheObject } from '@apollo/client'
import { IncomingMessage, ServerResponse } from 'http'

type ResolverContext = {
  req?: IncomingMessage
  res?: ServerResponse
}

const typePolicies = {
  Test: {
    keyFields: ['id'],
  },
  User: {
    keyFields: ['id'],
  },
}

let apolloClient: ApolloClient<NormalizedCacheObject>

function createIsomorphLink(context: ResolverContext = {}): any {
  if (typeof window === 'undefined') {
    const { SchemaLink } = require('@apollo/client/link/schema')
    const { schema } = require('backend/graphql/schema')
    return new SchemaLink({ schema, context })
  } else {
    const { HttpLink } = require('@apollo/client/link/http')
    return new HttpLink({
      uri: '/api/graphql',
      credentials: 'same-origin',
    })
  }
}

function createApolloClient(context?: ResolverContext): ApolloClient<NormalizedCacheObject> {
  return new ApolloClient({
    ssrMode: typeof window === 'undefined',
    link: createIsomorphLink(context),
    cache: new InMemoryCache({ typePolicies }),
  })
}

export function initializeApollo(
  initialState: any = null,
  // Pages with Next.js data fetching methods, like `getStaticProps`, can send
  // a custom context which will be used by `SchemaLink` to server render pages
  context?: ResolverContext
): ApolloClient<NormalizedCacheObject> {
  const _apolloClient = apolloClient ?? createApolloClient(context)

  // If your page has Next.js data fetching methods that use Apollo Client, the initial state
  // get hydrated here
  if (initialState) {
    // Get existing cache, loaded during client side data fetching
    const existingCache = _apolloClient.extract()
    // Restore the cache using the data passed from getStaticProps/getServerSideProps
    // combined with the existing cached data
    _apolloClient.cache.restore({ ...existingCache, ...initialState })
  }
  // For SSG and SSR always create a new Apollo Client
  if (typeof window === 'undefined') return _apolloClient
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient

  return _apolloClient
}

// eslint-disable-next-line
export function useApollo(initialState: any): ApolloClient<NormalizedCacheObject> {
  const store = useMemo(() => initializeApollo(initialState), [initialState])
  return store
}

最佳答案

您需要应用上下文解析器:

async contextResolver(ctx: Ctx): Promise<Ctx> {
    ctx.db = prisma

    return ctx
 },

const apolloServer = new ApolloServer({
  schema,
  context: contextResolver,
})
在 getServerSideProps 中:
export const getServerSideProps: GetServerSideProps = async (ctx) => {
  await contextResolver(ctx)
  const apolloClient = initializeApollo(null, ctx)

  await apolloClient.query({
    query: UserQuery,
    variables: { id: Number(ctx.query.id) },
  })

  return {
    props: { initialApolloState: apolloClient.cache.extract() },
  }
}

关于SSR getServerSideProps 上的 Next.js graphql 上下文为空 {},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64537328/

相关文章:

javascript - 更改页面时,Cypress 访问在 Next js 上不起作用

reactjs - CSVLink 在 `react-csv` npm 包中生成 HTML 而不是 CSV

typescript - 如何使用 Typescript 和 Node 生成 REST API 文档?

reactjs - useState set 方法没有立即反射(reflect)变化(Stackoverflow 中建议的解决方案不起作用)

laravel - 如何将 Nexts.js 添加到 Laravel

next.js - 如何在下一个js应用程序文件夹中使用vercel og图像?

python - Flask 和 NextJS - CORS 不适用于 POST

azure - SendGrid 电子邮件在本地工作,但不适用于 Azure 应用服务

javascript - Tailwind CSS 颜色不适用于下一个 js 组件。你如何应用背景颜色?

javascript - 如何在 Next.js 的事件页面上设置链接组件的样式