Apollo 3 React本地状态无法读取GraphQL自定义类型响应式变量
问题根因
你遇到的自定义类型字段读取返回null的问题,核心是3个配置错误:
- 字段策略配置位置错误:你在
Query.user的typePolicy里写了__typename: 'User',这个配置不属于字段策略的合法属性,__typename是存储的对象本身携带的元信息,不需要在策略里手动声明,无效配置会干扰Apollo的正常解析。 - 响应式变量初始值类型不匹配:
userVar初始值设为空字符串"",但后续存储的是用户对象,类型不一致会导致Apollo初始化字段时的异常。 - 本地查询不符合GraphQL规范:
GET_LOCAL_USER查询只声明了user @client,没有选择对象类型下的任何子字段。GraphQL规范要求对象类型的查询必须明确指定要返回的子字段,标量类型(比如你正常运行的isAuthenticated是Boolean标量)不需要子字段,这也是为什么布尔值查询正常、用户对象查询返回null的核心原因。
修复步骤
- 修正
cache.js配置- 把
userVar初始值从空字符串改为null,匹配未登录时无用户数据的状态,和后续存储的对象类型统一 - 删除
user字段策略里错误添加的__typename配置项,你从登录接口拿到的result.data.login.user本身已经自带__typename: 'User'字段,不需要手动声明
修正后的cache相关代码:
- 把
import { InMemoryCache, makeVar, gql } from '@apollo/client' export const isAuthenticatedVar = makeVar(!!localStorage.getItem('token')) // 初始值改为null export const userVar = makeVar(null) export const cache = new InMemoryCache({ typePolicies: { Query: { fields: { isAuthenticated: { read() { return isAuthenticatedVar() } }, user: { read() { return userVar() }, // 删除此处错误的__typename配置 } } } } }) export const IS_AUTHENTICATED = gql` query IS_AUTHENTICATED { isAuthenticated @client } `
- 补全本地查询的子字段
修改GET_LOCAL_USER查询,明确声明你需要获取的User类型下的子字段,和你typeDef里定义的字段保持一致即可:
export const GET_LOCAL_USER = gql` query GET_LOCAL_USER { user @client { id name surname email phone isAdmin isCoach isManager # 按需添加你需要使用的其他字段,比如adress } } `
- (可选)修正typeDef声明
如果你本地定义的User类型不是扩展自服务端已有的User类型,把extend type User改为type User即可;如果服务端接口本身已经返回过User类型,保留extend写法没有问题。
改完之后再调用client.readQuery({ query: GET_LOCAL_USER })就能正常拿到存储的用户对象,不会再返回null。
内容的提问来源于stack exchange,提问作者Dylan Di Vito
相关产品推荐
相关产品推荐

