Apollo客户端本地状态缓存竞争条件?

时间:2019-01-24 15:16:21

标签: javascript reactjs graphql apollo apollo-client

因此,我一直试图在React应用程序中使用apollo-boost来通过查询中的@client指令使用缓存来管理我的客户端状态,但是我遇到了一些问题。

基本上,我正在使用writeQuery()在组件中将boolean值写入本地应用状态(我们称其为组件A),并希望使用readQuery()在另一个组件(我们将其称为组件B)中获取该值。在componentDidUpdate方法中。事实是,在组件A中的writeQuery设置缓存/本地状态中的值之前,组件B中的readQuery()正在运行,因此组件B读取的值出现错误。

我已经通过使用setTimeout来延迟readQuery()来确认这一点,并且确实在使用了超时之后,该值是正确的,但是该解决方案无法信任,我可能不知道Apollo Client中的某些情况,因为对于本地状态管理,此功能非常基本。有提示吗?

我相信在Redux中可以解决此问题,因为状态是注入到props中的,这使得组件得以更新,因此,由于组件A是更改状态的组件,组件B甚至不必使用componentDidUpdate即可获得新值,因为状态将被注入并且组件B将被更新为正确的值。

任何帮助将不胜感激,如果我没有清楚自己的意思,对不起!

编辑:在Mutation解析器内部使用了writeQuery()。

1 个答案:

答案 0 :(得分:0)

诸如readQuerywriteQuery之类的方法旨在用于读取和修改突变内部的缓存。通常,不应在组件内部直接使用它们。通过调用readQuery,您只需从缓存中获取一次数据。相反,您应该使用Query组件。

const TODO_QUERY = gql`
  query GetTodos {
    todos @client {
      id
      text
      completed
    }
  }
`

<Query query={TODO_QUERY}>
  {({ data }) => {
    if (data.todos) return <ToDoListComponent todos={data.todos}/>
    return null
  }}
</Query>

Query组件订阅了对缓存的相关更改,因此data的值将在缓存时更新。

类似地,您应该对要对缓存进行的任何更改都创建适当的突变,然后利用Mutation组件实际对缓存进行突变。

const client = new ApolloClient({
  clientState: {
    defaults: {
      todos: []
    },
    resolvers: {
      Mutation: {
        addTodo: (_, { text }, { cache }) => {
          const previous = cache.readQuery({ query: TODO_QUERY })
          const newTodo = { id: nextTodoId++, text, completed: false, __typename: 'TodoItem' }
          const data = {
            todos: previous.todos.concat([newTodo]),
          }

          cache.writeQuery({ query, data })
          return newTodo
        },
      },
    }
  }
})

<Mutation mutation={ADD_TODO}>
  {(addTodo) => (
    // use addTodo to mutate the cache asynchronously
  )}
</Mutation>

请查看the docs以获得更多详细信息。