本地客户端上的Apollo不会触发本地解析器

时间:2020-05-11 18:49:07

标签: graphql apollo

在“本地状态客户端”(前端本地状态)的情况下,Apollo不会触发解析器。阿波罗2.7

有人知道为什么会发生吗?

这是设置:

Apollo客户

import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { HttpLink } from 'apollo-link-http'
import fetch from 'isomorphic-unfetch'

import { resolvers, typeDefs } from './resolvers';
import { initCache } from './init-cache';

export default function createApolloClient(initialState, ctx) {
  // The `ctx` (NextPageContext) will only be present on the server.
  // use it to extract auth headers (ctx.req) or similar.
  return new ApolloClient({
    ssrMode: Boolean(ctx),
    link: new HttpLink({
      uri: 'https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn', // Server URL (must be absolute)
      credentials: 'include', // Additional fetch() options like `credentials` or `headers`
      fetch,
    }),
    typeDefs,
    resolvers,
    connectToDevTools: true,
    cache: initCache({
                   robot: {
                     __typename: 'Robot',
                     name: 'Robbie',
                     status: 'live',
                    },

                  member: {
                     __typename: 'Member',
                     name: 'RFesagfd',
                     }
                   }),
     })
  }

类型和解析器(resolvers.js)

import gql from 'graphql-tag';

export const typeDefs = gql`
  type Robot {
    name: String!
    status: String!
  }

  type Member {
    name: String!
    isLogged: Boolean!
  }

`;

export const resolvers = {
  Member: {
    isLogged: (...args) => {
      console.log('args', args); // THIS NEVER TRIGGERS SOMEHOW
      return true;
    }
  }
};

查询

const GET_IS_MEMBER_LOGGED = gql`
  query isMemberLogged {
    member @client {
      name
      isLogged
    }
  }
`;

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

您需要定义本地查询的结果类型:

audit2allow

...和用于查询的解析器-不键入(因为您将整个查询修饰为本地)...但是您必须返回键入的数据

const typeDefs = gql`
  extend type Query {
    robot: Robot
    member: Member
  }

您还应该使用export const resolvers = { Query: { member: (...args) => { console.log('args', args); return { __typename: 'Member', name: 'some name', // read from cache isLogged: true // function result }; } } }; 进行缓存写入。

更新

假设您的缓存中有Memeber ...,您可以:

__typename

关于形状/数据组织-类型化(返回具有定义属性的形状对象)或简单化(分别返回所有属性)或混合,例如(某些全局应用程序状态)

// read (initialized with permanent) data:
const memberData = cache.readQuery(....
// f.e. it should have `__typename` and 'name`
// ... and 'decorate' it with derived properites
memberData.age = currentYear - memberData.birthYear;
memberData.isLogged = someFuncReturningBool();
return memberData; // Member type shaped object

答案 1 :(得分:0)

我找到了可能的解决方案。也许此信息对某人有用。 如果我们想省略查询解析器+字段解析器,并且想要拥有唯一的字段解析器,则需要使用 @client(always:true)

深入的说明

通常,Apollo客户端如何与Cache一起使用存在问题。 默认情况下,它缓存响应,下一次它将从缓存中获取缓存的结果(例如optimistic UI)。即使在客户端情况下,此行为也相同。

这意味着当我们在缓存中拥有初始模型时,即使我们通过@client指令,Apollo也会从缓存中获取并忽略解析器。 要解决此问题,并让Apollo知道即使我们有缓存的对象,也需要使用本地解析器,我们需要对首选字段或整个对象使用 @client(always:true)。我在下面做了一个例子。

附言不幸的是,我没有找到如何强制Apollo与不存在的字段一起使用的方法,因此,如果我们想为特定字段使用一些解析器,我们仍然需要定义初始字段值,即初始缓存模型,以使Apollo了解这个领域。之后,由于 @client(always:true),Apollo将使用解析器为此特定字段生成一些高计算输出。
一般来说,这没关系,因为我们应该知道模型中将具有哪种动态场。

Apollo客户

import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { HttpLink } from 'apollo-link-http'
import fetch from 'isomorphic-unfetch'

import { resolvers, typeDefs } from './resolvers';
import { initCache } from './init-cache';

export default function createApolloClient(initialState, ctx) {
  // The `ctx` (NextPageContext) will only be present on the server.
  // use it to extract auth headers (ctx.req) or similar.
  return new ApolloClient({
    ssrMode: Boolean(ctx),
    link: new HttpLink({
      uri: 'https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn', // Server URL (must be absolute)
      credentials: 'include', // Additional fetch() options like `credentials` or `headers`
      fetch,
    }),
    typeDefs,
    resolvers,
    connectToDevTools: true,
    cache: initCache({
                     author: {
                     __typename: 'Author',
                     posts: 0,
                     name: '' // NEED TO SET AN INITIAL VALUE
                     }
     })
  }

类型和解析器(resolvers.js)

import gql from 'graphql-tag';
import { print  } from 'graphql';

export const typeDefs = gql`
  type Author {
    posts: Int!
    name: String
  }

`;


export const resolvers = {
  Author: {
    name(author) {
      console.log('Author name resolver', author). // WORKS
      return 'NAME';
    },
  },

};

查询

const GET_AUTHOR = gql`
  query getAuthor {
    author {
      posts
      name @client(always: true)
    }
  }
`;