javascript - 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 解析器中使用。
解决方案
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>
请查看文档以获取更多详细信息。
推荐阅读
- sql - 为每个 ID 插入新记录的 SQL 脚本
- php - 显示收到的友谊请求数量的片段
- javascript - 如何删除除第一个元素之外的所有子元素?
- react-native - 在渲染功能之外导航
- android - 在js外定义onesignal_app_id
- angular - Angular 6 编译失败属性 tz 在 Moment 类型上不存在
- reactjs - 在 React 中跟踪 SVG 图像加载
- laravel - 我可以让用户单击一个按钮然后将某些内容添加到数据库中吗
- c# - EF Core - 可能导致循环或多个级联路径
- python - 有没有一种有效的方法在两个字符串之间分割一个字符串?