在变异后设置Apollo缓存/状态

时间:2018-04-25 11:36:04

标签: reactjs graphql apollo react-apollo apollo-client

我正在使用Apollo 2.0来管理我的graphQL API调用并处理我的反应应用程序的全局状态。

我正在尝试创建一个用户输入用户名和密码的登录屏幕,这会被发送到我的API进行身份验证,一旦成功,我想将全局状态isLoggedIn设置为{{1 }}

到目前为止,我能够使用一个使用true声明的突变来设置全局状态,因此它只关注本地状态。我有另一个突变,它使graphQL API调用并验证用户名/密码,然后返回成功/错误响应。

一旦API调用变异完成或失败,我希望能够设置@client

我的客户端具有以下默认状态和解析器设置如下:

isLoggedIn

然后在我的Login组件中,我有以下突变和查询,我在compose的帮助下作为HOC传递:

const httpLink = new HttpLink({
  uri: '/graphql',
  credentials: 'same-origin'
});

const cache = new InMemoryCache();

const stateLink = withClientState({
  cache,
  resolvers: {
    Mutation: {
      updateLoggedInStatus: (_, { isLoggedIn }, { cache }) => {
        const data = {
          loggedInStatus: {
            __typename: 'LoggedInStatus',
            isLoggedIn
          },
        };
        cache.writeData({ data });
        return null;
      },
    },
  },
  defaults: {
    loggedInStatus: {
      __typename: 'LoggedInStatus',
      isLoggedIn: false,
    },
  },
});

const link = ApolloLink.from([stateLink, httpLink])

const client = new ApolloClient({
  link,
  cache
});

export default client

因此,您可以看到我在提交登录表单时使用了const UPDATE_LOGGED_IN_STATUS = gql` mutation updateLoggedInStatus($isLoggedIn: Boolean) { updateLoggedInStatus(isLoggedIn: $isLoggedIn) @client }` const AUTHENTICATE = gql` mutation authenticate($username: String!, $password: String!) { auth(username: $username, password: $password) { username sales_channel full_name roles } }` const GET_AUTH_STATUS = gql` query { loggedInStatus @client { isLoggedIn } }` export default compose( graphql(GET_AUTH_STATUS, { props: ({ data: { loading, error, loggedInStatus } }) => { if (loading) { return { loading }; } if (error) { return { error }; } return { loading: false, loggedInStatus }; }, }), graphql(UPDATE_LOGGED_IN_STATUS, { props: ({ mutate }) => ({ updateLoggedInStatus: isLoggedIn => mutate({ variables: { isLoggedIn } }), }), }), graphql(AUTHENTICATE, { props: ({ mutate }) => ({ authenticate: (username, password) => mutate({ variables: { username, password } }), }), }) )(withRouter(Login));

然后我有this.props.authenticate(username, password)我可以更新客户端缓存/状态。

如何合并这些内容,以便我可以致电this.props.updateLoggedInStatus(Boolean),如果成功,请设置authenticate(),如果失败,请设置loggedInStatushasErrored排序

提前致谢。

编辑:

我试图在我的变异回调中处理更新状态。

errorMessage

有没有比这更好的方法呢?感到非常困惑,不得不等待回电。我原本以为我可以通过我的解析器将响应映射到我的缓存对象?

1 个答案:

答案 0 :(得分:1)

我认为你当前处理它的方式(调用authenticate然后updateLoggedInStatus)就像你要使用apollo-link-state一样干净简单。但是,首先使用apollo-link-state可能是矫枉过正。从Apollo的缓存中导出登录状态可能更简单。例如,您可以拥有这样的HOC:

import client from '../wherever/client'

const withLoggedInUser = (Component) => {
  const user = client.readFragment({
  id: 'loggedInUser', 
  fragment: gql`
    fragment loggedInUser on User { # or whatever your type is called
      username
      sales_channel
      full_name
      roles
      # be careful about what fields you list here -- even if the User
      # is in the cache, missing fields will result in an error being thrown
    }
  `
  })
  const isLoggedIn = !!user
  return (props) => <Component {...props} user={user} isLoggedIn={isLoggedIn}/>
}

请注意,我使用loggedInUser作为密钥。这意味着我们还必须在配置dataIdFromObject时使用InMemoryCache

import { InMemoryCache, defaultDataIdFromObject } from 'apollo-cache-inmemory'

const cache = new InMemoryCache({
  dataIdFromObject: object => {
    switch (object.__typename) {
      case 'User': return 'loggedInUser'
      // other types you don't want the default behavior for
      default: return defaultDataIdFromObject(object);
    }
  }
})