当前位置: 首页 > 知识库问答 >
问题:

突变后设置Apollo缓存/状态

宰父保臣
2023-03-14

我使用Apollo 2.0管理graphQL API调用,并处理react应用程序的全局状态。

我试图创建一个登录屏幕,用户在其中输入用户名和密码,这将发送到我的API进行身份验证,成功后,我想将isLoggedIn的全局状态设置为true。

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

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

我的客户端具有以下默认状态,并设置了如下解析程序:

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

然后在我的登录组件中,我有以下突变和查询,我在撰写的帮助下将其作为HOC传递:

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(用户名,密码),它在提交登录表单时使用。

然后我有了这个。道具。UpdateLogedinStatus(布尔值),我可以更新客户端缓存/状态。

如何组合这些,以便我可以调用验证(),如果成功,设置loggedInstatus,如果失败,设置hasErrorederrorMessage标志的排序

提前感谢。

编辑:

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

// Form submission handler
onSubmit = async ({ username, password }) => {
    this.setState({loading: true})
    this.props.authenticate(username, password)
      .then(res => {
        this.setState({loading: false})
        this.props.updateLoggedInStatus(true)
      })
      .catch(err => {
        this.setState({loading: false, errorMessage: err.message})
        console.log('err', err)
      })
  }

还有比这更好的方法吗?要等回电话,感觉很复杂。我本以为可以通过解析器将响应映射到缓存对象?

共有1个答案

伯庆
2023-03-14

我认为您目前处理它的方式(调用身份验证,然后调用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作为键。这意味着我们在配置InMemoryCache时还必须使用dataIdFromObject

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);
    }
  }
})
 类似资料:
  • set 设置普通类型的值 设置 set set(key: string, value: string expiryMode: string[ EX 秒 PX 分钟 ], time: number ) key: 键名称 value:存储的值 expiryMode:添加过期时间类型 EX 秒 PX 分钟 time:过期时间 // 存储一个key为gender,value 为 男人的数据,10秒后过期

  • 问题内容: 因此,我正在尝试为从服务器获取数据的编辑组件设置初始状态,现在应该可以在组件状态下对其进行编辑。但是当我尝试这样做时: 因为这是在渲染中,所以我陷入了无限循环。我不应该将组件状态与查询组件一起使用吗?如果没有,那还有什么选择呢? 问题答案: 无论哪个组件需要此数据作为状态,都应在组件内部进行渲染,然后将数据作为道具传递给它。例如:

  • 我在服务器上使用GraphQL和mongoose。 当发生验证错误时,GraphQL突变发送状态代码为200的响应。在客户端,响应如下所示: 我想使用阿波罗客户端突变promise的功能访问验证错误。类似: 如何做到这一点?

  • 我正在尝试使用update:在执行变异后更新查询。问题是存储区中的查询应用了几个不同的变量,我想更新查询并使用相同的变量返回它。 我在文档中发现,updateQueries有一个选项可以包含queryVariables,queryVariables是执行查询时使用的最后一组变量。 我没有找到任何描述如何从更新内部检索queryVariables或类似内容的内容。 更新内部:我可以使用 它将返回一个

  • 我有一个React函数组件,沿着遗留的JQuery应用程序运行。在JQuery元素上调用事件处理程序时,传递当前React状态默认值为初始状态值,而不是更新后的状态值。 已验证的x状态正在通过useEffect钩子更改,但在调用事件侦听器时,x设置为初始状态值,而不是更新后的状态值。 不会显示任何错误消息。在本文的上述代码中,我希望onXSave方法调用中的x状态为true,但它一直显示为fals

  • 反应阿波罗客户端应用程序。我试图使用readQuery从缓存中读取数据,但无法读取缓存字段。 这里有一个纲要: 组件调用,它执行我的查询并缓存结果。查询返回类型。一切都很好,开发工具显示包含一个名为getPost的字段和该帖子。 有一个子组件,它会在单击时删除评论。它调用并删除评论。查询返回类型。 Post有一个注释数组,现在我需要在缓存中更新它的数组并删除已删除的注释。我使用突变中的函数来获取缓