如何避免在React组件中对GraphQL嵌套片段调用useFragment?
问题:如何避免对GraphQL嵌套子片段调用useFragment?
现有通过GraphQL Codegen生成的嵌套片段及关联子片段代码如下:
import { graphql } from '../../generated/graphql'; export const regularErrorFragmentDocument = graphql(` fragment regularError on FieldError { field message } `); export const regularUserFragmentDocument = graphql(` fragment regularUser on User { id username } `); export const regularUserResponseFragmentDocument = graphql(` fragment regularUserResponse on UserResponse { errors { ...regularError } user { ...regularUser } } `);
在React组件中的使用方式如下:
if (response.data?.login) { const data = useFragment(regularUserResponseFragmentDocument, response.data.login); const errorsData = useFragment(regularErrorFragmentDocument, data.errors); if (errorsData) { setErrors(toErrorMap([...errorsData])); } const userData = useFragment(regularUserFragmentDocument, data.user); if (userData) { await router.push('/'); } }
请问是否存在方法可以避免对其中的嵌套子片段调用useFragment?
回答
完全可以避免重复调用useFragment,核心是让主片段返回的数据自动包含子片段的类型与字段信息,无需单独对子片段执行useFragment,以下是两种可行方案:
方案1:配置GraphQL Codegen自动处理嵌套片段类型
确保你的GraphQL Codegen配置(如codegen.ts)启用了片段类型合并(使用@graphql-codegen/client-preset预设即可默认支持),这样生成的主片段类型会自动包含嵌套子片段的所有字段。
修改后组件中的使用代码可简化为:
if (response.data?.login) { const data = useFragment(regularUserResponseFragmentDocument, response.data.login); if (data.errors) { setErrors(toErrorMap([...data.errors])); } if (data.user) { await router.push('/'); } }
此时data.errors和data.user会直接携带regularError、regularUser片段定义的字段,无需额外调用子片段的useFragment。
方案2:内联子片段字段(不推荐)
如果不想调整Codegen配置,也可以直接在主片段中写出子片段的字段,替代子片段引用:
export const regularUserResponseFragmentDocument = graphql(` fragment regularUserResponse on UserResponse { errors { field message } user { id username } } `);
这种方式能直接通过主片段的useFragment获取完整字段,但缺点是字段代码重复,后续维护子片段时需要同步修改主片段,不利于代码复用。
关键说明
当主片段引用子片段时,GraphQL Codegen会自动合并类型信息,只要配置正确,useFragment返回的data对象就会包含嵌套字段的完整类型,之前的重复调用是因为类型推断未生效或Codegen配置未正确处理嵌套片段。
内容的提问来源于stack exchange,提问作者El Anonimo
相关产品推荐
相关产品推荐

