首页 > 解决方案 > Apollo 客户端本地状态缓存竞争条件?

问题描述

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

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

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

我相信在 Redux 中解决了这个问题,因为状态被注入到 props 中,这使得组件更新,所以组件 A 是改变状态的组件 B 甚至不必使用 componentDidUpdate 来获取新的值,因为状态将被注入,并且组件 B 将使用正确的值进行更新。

任何帮助将不胜感激,如果我没有说清楚,对不起!

编辑: writeQuery() 正在 Mutation 解析器中使用。

标签: javascriptreactjsgraphqlapolloapollo-client

解决方案


readQuery和之类的方法writeQuery旨在用于读取和修改突变内部的缓存。一般来说,它们不应该直接在组件内部使用。通过调用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>

请查看文档以获取更多详细信息。


推荐阅读