OneGraph 和 Graphql Codegen 输出带有数值的枚举
OneGraph and Graphql Codegen outputs enums with numeric values
因此,我只是将项目的整个代码库从使用直接的 Headless Wordpress GraphQL 端点迁移到使用 OneGraph 以获得 Google+Facebook 业务支持。 OneGraph 是一个了不起的工具,实际上我打算在无头 WordPress 上编写的技术课程中使用它。无论如何,我收到这个 apollo 错误,它引用了输出代码生成器。这是错误:
graphQLErrors: [
{
message: 'Variable "$idTypeFoot" got invalid value 2; Expected type MenuNodeIdTypeEnum.',
path: [Array],
extensions: [Object]
},
{
message: 'Variable "$idTypeFoot" got invalid value 2; Expected type MenuNodeIdTypeEnum.',
path: [Array],
extensions: [Object]
}
],
这是我的 generated/graphql.tsx 文件中的输出代码生成定义:
export enum WordpressMenuNodeIdTypeEnum {
/** Identify a menu node by the Database ID. */
DATABASE_ID = 0,
/** Identify a menu node by the (hashed) Global ID. */
ID = 1,
/** Identify a menu node by it's name */
NAME = 2
}
这是在将我的代码库迁移到 onegraph 之前相同枚举的先前定义:
/** The Type of Identifier used to fetch a single node. Default is "ID". To be used along with the "id" field. */
export enum MenuNodeIdTypeEnum {
/** Identify a menu node by the Database ID. */
DatabaseId = 'DATABASE_ID',
/** Identify a menu node by the (hashed) Global ID. */
Id = 'ID',
/** Identify a menu node by it's name */
Name = 'NAME'
}
这是父查询中使用的 dynamic-nav-fields.graphql
部分:
fragment DynamicNavFragment on WordpressMenuItem {
id
label
path
parentId
}
这里是 dynamic-nav.graphql
父查询:
# import DynamicNavFragment from './Partials/dynamic-nav-fields.graphql'
query DynamicNav(
$idHead: ID!
$idTypeHead: WordpressMenuNodeIdTypeEnum!
$idFoot: ID!
$idTypeFoot: WordpressMenuNodeIdTypeEnum!
) {
Header: wordpress {
menu(id: $idHead, idType: $idTypeHead) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
}
}
Footer: wordpress {
menu(id: $idFoot, idType: idTypeFoot) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
这是我的 codegen.yml 配置文件:
overwrite: true
schema:
${WORDPRESS_API_URL_YML}:
headers:
Authorization: Bearer ${WORDPRESS_AUTH_REFRESH_TOKEN_YML}
documents: 'graphql/**/*.graphql'
generates:
graphql/generated/graphql.tsx:
plugins:
- typescript:
constEnums: false
enumsAsTypes: false
numericEnums: true
futureProofEnums: false
enumsAsConst: false
onlyOperationTypes: false
maybeValue: T | null | undefined
noExport: false
enumPrefix: true
fieldWrapperValue: T
wrapFieldDefinitions: true
skipTypename: false
nonOptionalTypename: false
useTypeImports: false
avoidOptionals: true
declarationKind:
input: interface
type: interface
- typescript-operations:
declarationKind:
input: interface
type: interface
avoidOptionals: true
exportFragmentSpreadSubTypes: true
- typescript-react-apollo:
addDocBlocks: true
reactApolloVersion: 3
documentMode: documentNodeImportFragments
config:
maybeValue: T | null | undefined
declarationKind:
input: interface
type: interface
documentNodeImportFragments: true
reactApolloVersion: 3
withHooks: true
withHOC: false
avoidOptionals: true
withComponent: false
exportFragmentSpreadSubTypes: true
addDocBlocks: true
graphql/graphql.schema.graphql:
plugins:
- schema-ast
config:
commentDescriptions: true
graphql/graphql.schema.json:
plugins:
- introspection
config:
commentDescriptions: true
hooks:
afterAllFileWrite:
- prettier --write
为什么 OneGraph 将生成的 Enum 值替换为 apollo 客户端无法读取的数字?如果有人知道如何解决这个问题,请告诉我
更新 — 查看@sgrove 的回答,他很棒,帮我解决了问题!
好的,我有两个选择:(1) 覆盖每个枚举,该枚举是从 __type 之前 或 的代表字符串值转换而来的 (2) 对这些进行硬编码值。要获得自定义枚举值,我必须将以下内容添加到我的 codegen.yml:
config:
enumValues:
WordpressMenuNodeIdTypeEnum: '@/types/global-enums#WordpressMenuNodeIdTypeEnum'
指示生成的代码从@/types/global-enums.ts
导入这个枚举定义
/** The Type of Identifier used to fetch a single node. Default is "ID". To be used along with the "id" field. */
export enum WordpressMenuNodeIdTypeEnum {
/** Identify a menu node by the Database ID. */
DatabaseId = 'DATABASE_ID',
/** Identify a menu node by the (hashed) Global ID. */
Id = 'ID',
/** Identify a menu node by it's name */
Name = 'NAME'
}
然而,我随后 运行 进入另一个问题,并决定直接在我的 graphql 模式中硬编码 WordpressMenuNodeIdTypeEnum 的 NAME
值:
# import DynamicNavFragment from './Partials/dynamic-nav-fields.graphql'
query DynamicNav($idHead: ID!, $idFoot: ID!) {
Header: wordpress {
menu(id: $idHead, idType: NAME) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
}
}
Footer: wordpress {
menu(id: $idFoot, idType: NAME) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
然后我 运行 遇到了 apollo 缓存的另一个问题,因为顶级 ServicesTopQuery 和 DynamicNavQuery 都有一个共享的顶级 wordpress
字段和相应的 __typename " WordPressRootQuery..
ServicesTopQuery
和 ServicesTopQueryVariables
的代码生成定义:
export type ServicesTopQueryVariables = Exact<{
popular: Scalars['String'];
other: Scalars['String'];
}>;
export type ServicesTopQuery = { __typename?: 'Query' } & {
popular: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
services: Maybe<
{ __typename?: 'WordpressRootQueryToServiceConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressRootQueryToServiceConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressService';
} & ServiceFieldsTopFragment
>;
}
>
>
>;
}
>;
}
>;
other: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
services: Maybe<
{ __typename?: 'WordpressRootQueryToServiceConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressRootQueryToServiceConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressService';
} & ServiceFieldsTopFragment
>;
}
>
>
>;
}
>;
}
>;
};
DynamicNavQuery
和 DynamicNavQueryVariables
的代码生成定义:
export type DynamicNavQueryVariables = Exact<{
idHead: Scalars['ID'];
idFoot: Scalars['ID'];
}>;
export type DynamicNavQuery = { __typename?: 'Query' } & {
Header: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
menu: Maybe<
{ __typename?: 'WordpressMenu' } & {
menuItems: Maybe<
{ __typename?: 'WordpressMenuToMenuItemConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuToMenuItemConnectionEdge';
} & {
node: Maybe<
{ __typename?: 'WordpressMenuItem' } & {
childItems: Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnection';
} & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnectionEdge';
} & {
node: Maybe<
{ __typename?: 'WordpressMenuItem' } & {
childItems: Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnection';
} & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressMenuItem';
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
}
>;
}
>;
Footer: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
menu: Maybe<
{ __typename?: 'WordpressMenu' } & {
menuItems: Maybe<
{ __typename?: 'WordpressMenuToMenuItemConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuToMenuItemConnectionEdge';
} & {
node: Maybe<
{ __typename?: 'WordpressMenuItem' } & {
childItems: Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnection';
} & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressMenuItem';
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
}
>;
}
>;
};
来自 pages/index.tsx
的代码,其中最初填充了 DynamicNavQuery 数据,然后迅速被 ServicesTopQuery 数据覆盖
import { Container } from '@/components/UI';
import { initializeApollo, addApolloState } from '@/lib/apollo';
import { LandingHero } from '@/components/Landing';
import ServiceTopCoalesced from '@/components/ServicesTop/services-top-coalesced';
import AppLayout from '@/components/Layout/layout';
import {
GetStaticPropsContext,
GetStaticPropsResult,
InferGetStaticPropsType
} from 'next';
import {
ServicesTopQuery,
ServicesTopQueryVariables,
ServicesTopDocument,
DynamicNavDocument,
DynamicNavQueryVariables,
DynamicNavQuery
} from '@/graphql/generated/graphql';
export function Index({
other,
popular,
Header,
Footer
}: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<>
<AppLayout
title={'✂ The Fade Room Inc. ✂'}
Header={Header}
Footer={Footer}
hero={<LandingHero />}
>
<Container clean className='fit'>
<ServiceTopCoalesced other={other} popular={popular} />
</Container>
</AppLayout>
</>
);
}
export async function getStaticProps(
ctx: GetStaticPropsContext
): Promise<
GetStaticPropsResult<{
other: ServicesTopQuery['other'];
popular: ServicesTopQuery['popular'];
Header: DynamicNavQuery['Header'];
Footer: DynamicNavQuery['Footer'];
}>
> {
const apolloClient = initializeApollo();
await apolloClient.query<
DynamicNavQuery,
DynamicNavQueryVariables
>({
query: DynamicNavDocument,
variables: {
idHead: 'Header',
idFoot: 'Footer'
}
});
await apolloClient.query<
ServicesTopQuery,
ServicesTopQueryVariables
>({
query: ServicesTopDocument,
variables: {
other: 'all',
popular: 'popular-service'
}
});
return addApolloState(apolloClient, {
props: {},
revalidate: 10
});
}
export default Index;
DynamicNavQuery 数据已按预期填充,然后我的后备加载组件在初始 DOM 渲染后渲染了四分之一秒左右,然后 DynamicNavQuery 数据消失并填充了 ServicesTopQuery 数据。因此,现有的缓存数据被传入数据覆盖,在 apollo 客户端缓存中共享相同的顶级字段 wordpress
和 __typename WordPressRootQuery
。为了纠正这种行为,我查阅了 apollo 文档并使用以下内容更新了 new InMemoryCache
class 的实例化:
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
wordpress: {
merge(existing, incoming, { mergeObjects }) {
// invoking nested merge functions
return mergeObjects(existing, incoming);
}
}
}
}
}
})
});
以上内容阻止了现有的 wordpress
字段数据被传入的 wordpress
字段数据覆盖,从而解决了该问题。从无头 WordPress 端点迁移到 OneGraph 端点的过程证明比最初预期的要麻烦,所以我想我会跟进一个详细的响应,以防有人在路上遇到类似的问题。
tldr;将 codegen.yml
更改为使用 numericEnums: false
:
generates:
graphql/generated/graphql.tsx:
plugins:
- typescript:
numericEnums: false
为了追踪这一点,我采用了 WordpressMenuNodeIdTypeEnum
的 GraphQL SDL 定义:
enum WordpressMenuNodeIdTypeEnum {
# Identify a menu node by the Database ID.
DATABASE_ID
# Identify a menu node by the (hashed) Global ID.
ID
# Identify a menu node by it's name
NAME
}
连同之前在 codegen.yml
中的 numericEnums: true
设置,并在 https://www.graphql-code-generator.com 的操场上使用了它们
如您在屏幕截图中所见,SDL 定义被编译为数字枚举(运行时 typescript 枚举的标准)
然后我用 numericEnums: false
进行了测试:
并且该输出看起来像您期望的那样,其中 WordpressMenuNodeIdTypeEnum.Name
等于 "NAME"
,因此 Apollo 获得预期值而不是运行时打字稿枚举值(2
).
因此,我只是将项目的整个代码库从使用直接的 Headless Wordpress GraphQL 端点迁移到使用 OneGraph 以获得 Google+Facebook 业务支持。 OneGraph 是一个了不起的工具,实际上我打算在无头 WordPress 上编写的技术课程中使用它。无论如何,我收到这个 apollo 错误,它引用了输出代码生成器。这是错误:
graphQLErrors: [
{
message: 'Variable "$idTypeFoot" got invalid value 2; Expected type MenuNodeIdTypeEnum.',
path: [Array],
extensions: [Object]
},
{
message: 'Variable "$idTypeFoot" got invalid value 2; Expected type MenuNodeIdTypeEnum.',
path: [Array],
extensions: [Object]
}
],
这是我的 generated/graphql.tsx 文件中的输出代码生成定义:
export enum WordpressMenuNodeIdTypeEnum {
/** Identify a menu node by the Database ID. */
DATABASE_ID = 0,
/** Identify a menu node by the (hashed) Global ID. */
ID = 1,
/** Identify a menu node by it's name */
NAME = 2
}
这是在将我的代码库迁移到 onegraph 之前相同枚举的先前定义:
/** The Type of Identifier used to fetch a single node. Default is "ID". To be used along with the "id" field. */
export enum MenuNodeIdTypeEnum {
/** Identify a menu node by the Database ID. */
DatabaseId = 'DATABASE_ID',
/** Identify a menu node by the (hashed) Global ID. */
Id = 'ID',
/** Identify a menu node by it's name */
Name = 'NAME'
}
这是父查询中使用的 dynamic-nav-fields.graphql
部分:
fragment DynamicNavFragment on WordpressMenuItem {
id
label
path
parentId
}
这里是 dynamic-nav.graphql
父查询:
# import DynamicNavFragment from './Partials/dynamic-nav-fields.graphql'
query DynamicNav(
$idHead: ID!
$idTypeHead: WordpressMenuNodeIdTypeEnum!
$idFoot: ID!
$idTypeFoot: WordpressMenuNodeIdTypeEnum!
) {
Header: wordpress {
menu(id: $idHead, idType: $idTypeHead) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
}
}
Footer: wordpress {
menu(id: $idFoot, idType: idTypeFoot) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
这是我的 codegen.yml 配置文件:
overwrite: true
schema:
${WORDPRESS_API_URL_YML}:
headers:
Authorization: Bearer ${WORDPRESS_AUTH_REFRESH_TOKEN_YML}
documents: 'graphql/**/*.graphql'
generates:
graphql/generated/graphql.tsx:
plugins:
- typescript:
constEnums: false
enumsAsTypes: false
numericEnums: true
futureProofEnums: false
enumsAsConst: false
onlyOperationTypes: false
maybeValue: T | null | undefined
noExport: false
enumPrefix: true
fieldWrapperValue: T
wrapFieldDefinitions: true
skipTypename: false
nonOptionalTypename: false
useTypeImports: false
avoidOptionals: true
declarationKind:
input: interface
type: interface
- typescript-operations:
declarationKind:
input: interface
type: interface
avoidOptionals: true
exportFragmentSpreadSubTypes: true
- typescript-react-apollo:
addDocBlocks: true
reactApolloVersion: 3
documentMode: documentNodeImportFragments
config:
maybeValue: T | null | undefined
declarationKind:
input: interface
type: interface
documentNodeImportFragments: true
reactApolloVersion: 3
withHooks: true
withHOC: false
avoidOptionals: true
withComponent: false
exportFragmentSpreadSubTypes: true
addDocBlocks: true
graphql/graphql.schema.graphql:
plugins:
- schema-ast
config:
commentDescriptions: true
graphql/graphql.schema.json:
plugins:
- introspection
config:
commentDescriptions: true
hooks:
afterAllFileWrite:
- prettier --write
为什么 OneGraph 将生成的 Enum 值替换为 apollo 客户端无法读取的数字?如果有人知道如何解决这个问题,请告诉我
更新 — 查看@sgrove 的回答,他很棒,帮我解决了问题!
好的,我有两个选择:(1) 覆盖每个枚举,该枚举是从 __type 之前 或 的代表字符串值转换而来的 (2) 对这些进行硬编码值。要获得自定义枚举值,我必须将以下内容添加到我的 codegen.yml:
config:
enumValues:
WordpressMenuNodeIdTypeEnum: '@/types/global-enums#WordpressMenuNodeIdTypeEnum'
指示生成的代码从@/types/global-enums.ts
导入这个枚举定义/** The Type of Identifier used to fetch a single node. Default is "ID". To be used along with the "id" field. */
export enum WordpressMenuNodeIdTypeEnum {
/** Identify a menu node by the Database ID. */
DatabaseId = 'DATABASE_ID',
/** Identify a menu node by the (hashed) Global ID. */
Id = 'ID',
/** Identify a menu node by it's name */
Name = 'NAME'
}
然而,我随后 运行 进入另一个问题,并决定直接在我的 graphql 模式中硬编码 WordpressMenuNodeIdTypeEnum 的 NAME
值:
# import DynamicNavFragment from './Partials/dynamic-nav-fields.graphql'
query DynamicNav($idHead: ID!, $idFoot: ID!) {
Header: wordpress {
menu(id: $idHead, idType: NAME) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
}
}
Footer: wordpress {
menu(id: $idFoot, idType: NAME) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
然后我 运行 遇到了 apollo 缓存的另一个问题,因为顶级 ServicesTopQuery 和 DynamicNavQuery 都有一个共享的顶级 wordpress
字段和相应的 __typename " WordPressRootQuery..
ServicesTopQuery
和 ServicesTopQueryVariables
的代码生成定义:
export type ServicesTopQueryVariables = Exact<{
popular: Scalars['String'];
other: Scalars['String'];
}>;
export type ServicesTopQuery = { __typename?: 'Query' } & {
popular: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
services: Maybe<
{ __typename?: 'WordpressRootQueryToServiceConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressRootQueryToServiceConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressService';
} & ServiceFieldsTopFragment
>;
}
>
>
>;
}
>;
}
>;
other: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
services: Maybe<
{ __typename?: 'WordpressRootQueryToServiceConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressRootQueryToServiceConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressService';
} & ServiceFieldsTopFragment
>;
}
>
>
>;
}
>;
}
>;
};
DynamicNavQuery
和 DynamicNavQueryVariables
的代码生成定义:
export type DynamicNavQueryVariables = Exact<{
idHead: Scalars['ID'];
idFoot: Scalars['ID'];
}>;
export type DynamicNavQuery = { __typename?: 'Query' } & {
Header: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
menu: Maybe<
{ __typename?: 'WordpressMenu' } & {
menuItems: Maybe<
{ __typename?: 'WordpressMenuToMenuItemConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuToMenuItemConnectionEdge';
} & {
node: Maybe<
{ __typename?: 'WordpressMenuItem' } & {
childItems: Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnection';
} & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnectionEdge';
} & {
node: Maybe<
{ __typename?: 'WordpressMenuItem' } & {
childItems: Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnection';
} & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressMenuItem';
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
}
>;
}
>;
Footer: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
menu: Maybe<
{ __typename?: 'WordpressMenu' } & {
menuItems: Maybe<
{ __typename?: 'WordpressMenuToMenuItemConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuToMenuItemConnectionEdge';
} & {
node: Maybe<
{ __typename?: 'WordpressMenuItem' } & {
childItems: Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnection';
} & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressMenuItem';
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
}
>;
}
>;
};
来自 pages/index.tsx
的代码,其中最初填充了 DynamicNavQuery 数据,然后迅速被 ServicesTopQuery 数据覆盖
import { Container } from '@/components/UI';
import { initializeApollo, addApolloState } from '@/lib/apollo';
import { LandingHero } from '@/components/Landing';
import ServiceTopCoalesced from '@/components/ServicesTop/services-top-coalesced';
import AppLayout from '@/components/Layout/layout';
import {
GetStaticPropsContext,
GetStaticPropsResult,
InferGetStaticPropsType
} from 'next';
import {
ServicesTopQuery,
ServicesTopQueryVariables,
ServicesTopDocument,
DynamicNavDocument,
DynamicNavQueryVariables,
DynamicNavQuery
} from '@/graphql/generated/graphql';
export function Index({
other,
popular,
Header,
Footer
}: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<>
<AppLayout
title={'✂ The Fade Room Inc. ✂'}
Header={Header}
Footer={Footer}
hero={<LandingHero />}
>
<Container clean className='fit'>
<ServiceTopCoalesced other={other} popular={popular} />
</Container>
</AppLayout>
</>
);
}
export async function getStaticProps(
ctx: GetStaticPropsContext
): Promise<
GetStaticPropsResult<{
other: ServicesTopQuery['other'];
popular: ServicesTopQuery['popular'];
Header: DynamicNavQuery['Header'];
Footer: DynamicNavQuery['Footer'];
}>
> {
const apolloClient = initializeApollo();
await apolloClient.query<
DynamicNavQuery,
DynamicNavQueryVariables
>({
query: DynamicNavDocument,
variables: {
idHead: 'Header',
idFoot: 'Footer'
}
});
await apolloClient.query<
ServicesTopQuery,
ServicesTopQueryVariables
>({
query: ServicesTopDocument,
variables: {
other: 'all',
popular: 'popular-service'
}
});
return addApolloState(apolloClient, {
props: {},
revalidate: 10
});
}
export default Index;
DynamicNavQuery 数据已按预期填充,然后我的后备加载组件在初始 DOM 渲染后渲染了四分之一秒左右,然后 DynamicNavQuery 数据消失并填充了 ServicesTopQuery 数据。因此,现有的缓存数据被传入数据覆盖,在 apollo 客户端缓存中共享相同的顶级字段 wordpress
和 __typename WordPressRootQuery
。为了纠正这种行为,我查阅了 apollo 文档并使用以下内容更新了 new InMemoryCache
class 的实例化:
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
wordpress: {
merge(existing, incoming, { mergeObjects }) {
// invoking nested merge functions
return mergeObjects(existing, incoming);
}
}
}
}
}
})
});
以上内容阻止了现有的 wordpress
字段数据被传入的 wordpress
字段数据覆盖,从而解决了该问题。从无头 WordPress 端点迁移到 OneGraph 端点的过程证明比最初预期的要麻烦,所以我想我会跟进一个详细的响应,以防有人在路上遇到类似的问题。
tldr;将 codegen.yml
更改为使用 numericEnums: false
:
generates:
graphql/generated/graphql.tsx:
plugins:
- typescript:
numericEnums: false
为了追踪这一点,我采用了 WordpressMenuNodeIdTypeEnum
的 GraphQL SDL 定义:
enum WordpressMenuNodeIdTypeEnum {
# Identify a menu node by the Database ID.
DATABASE_ID
# Identify a menu node by the (hashed) Global ID.
ID
# Identify a menu node by it's name
NAME
}
连同之前在 codegen.yml
中的 numericEnums: true
设置,并在 https://www.graphql-code-generator.com 的操场上使用了它们
如您在屏幕截图中所见,SDL 定义被编译为数字枚举(运行时 typescript 枚举的标准)
然后我用 numericEnums: false
进行了测试:
并且该输出看起来像您期望的那样,其中 WordpressMenuNodeIdTypeEnum.Name
等于 "NAME"
,因此 Apollo 获得预期值而不是运行时打字稿枚举值(2
).