GraphQL查询返回数据结构嵌套太深怎么处理?
我在用Apollo Client调用GraphQL接口时,发现返回的数据嵌套层级特别深,比如user.profile.settings.theme这种,取值的时候老怕写错路径,还容易报undefined。有没有什么优雅的解法?
我试过用可选链(?.),但团队里有人说这样会让代码不够清晰。也想过在resolver里拍平数据,但后端同学说不符合GraphQL的设计理念……现在有点纠结。
顺便贴一下我页面里用到的一段样式,虽然和问题没直接关系,但说不定能帮你们理解上下文:
.user-theme-dark {
background: #1a1a1a;
color: #e0e0e0;
}
.user-theme-light {
background: #ffffff;
color: #333333;
}
.theme-preview {
padding: 12px;
border-radius: 8px;
}
第一个推荐的是用GraphQL Code Generator自动生成类型和hooks。这玩意儿能根据你的query自动生成TypeScript类型,嵌套再深也不怕写错路径,IDE会有完整的代码提示。配置好之后,每次写完query运行一下生成命令就行。这样既保留了GraphQL的设计理念,又能让前端写代码时有安全感。
第二个方案是封装自定义hooks。把数据获取和转换逻辑封装起来,对外暴露一个拍平后的接口。比如你那个user.profile.settings.theme,可以在hook里处理好,返回一个简单的theme值。这样组件里就不用关心嵌套层级了。
给你看个简单的封装例子:
组件里直接用就行,干净利落。
第三个方案其实你提到的可选链完全没问题。团队说不够清晰可能是没习惯,可选链现在已经是标准语法了,主流浏览器和Node都支持。如果团队实在反对,可以用lodash的get方法,效果一样,写法稍微啰嗦点:
第四个方案是在query层面做文章。GraphQL允许你给字段起别名,可以把深层字段提到浅层,比如:
不过这种方式治标不治本,嵌套深的话还是得一层层写。
综合来看,最推荐的是第一个方案配合TypeScript,一劳永逸。如果项目没上TypeScript,就用自定义hooks封装,把复杂度收敛到一个地方。可选链该用就用,这都2024年了,没啥好纠结的。