如何从阿波罗缓存中获取更新的数据
How to get updated data from apollo cache
Apollo 客户端有类似 mapStateToProps
(Redux) 的东西吗?
假设我有一个组件,查询后我知道缓存中有数据,所以我会做类似的事情:
class Container extends React.Component {
...
...
render() {
const notes = this.props.client.readFragment(NOTES_FRAGMENT)
// notes has everything I need
return (<Child notes={notes} />);
}
}
export default WithApollo(Container);
然而,当我有一个兄弟组件调用突变并进行更新时,<Child />
组件的道具永远不会得到更新。
class AnotherContainer extends React.Component {
render() {
return(
<Mutation
mutation={UPDATE_NOTE}
update={(cache, {data: {updateNote}}) =? {
const list = cache.readFragment({
fragment: NOTES_FRAGMENT
})
// manipulate list
cache.writeFragment({fragment:NOTES_FRAGMENT, data })
}
}
)
}
}
所以我的问题是,每当我执行 writeFragment 时,如何更新 <Child />
组件的道具?有没有像 mapStateToProps 之类的东西 "connect" notes
缓存的道具,所以每当它更新时,都会触发 React 生命周期?
react-apollo
提供了三种侦听缓存变化的方法:1) Query component, 2) the graphql HOC,以及 3) 直接使用客户端调用 watchQuery
。在所有这三种情况下,您都提供了一些查询和任何适当的选项,并且您获得了一种初始获取该查询并侦听其更新的方法。
这里的关键是 queries,而不是 fragments 是读取缓存的预期载体。 readFragment
方法仅作为一次读取缓存的便捷方式(通常在突变后更改缓存的上下文中)并且不提供任何类型的反应性。
所以,最重要的是,将您的组件包装在 Query
组件或 graphql
HOC 中,您将可以访问在缓存中反映查询结果的 props,并且会在以下时间更新缓存更新(与 connect
ed 组件的方式相同)。
此时您可能会想到一些事情:
"But I don't need to make another server request!" 不用担心——默认情况下,Apollo 只会请求一次相同的查询,并将在所有后续调用中使用缓存。您可以通过为查询设置适当的 fetch policy 来修改此行为。这包括一个 cache-only
策略,它只会从缓存中提取数据(尽管默认的 cache-first
策略对于大多数用例来说已经足够了)。
"But I don't have a query to work with!" 如果您将写入缓存作为持久化某些客户端状态的一种方式,那么您应该使用 apollo-link-state这样做。
"But I don't need the entire query result, just a part of it!" graphql
HOC 提供了一个 props
函数,您可以将其传递给可以让您转换查询数据的配置成任何你想使用的形状。将渲染道具模式与 Query
组件一起使用时,并不真正需要相同的功能——您可以直接操作渲染道具。在任何一种情况下,编写一些可以在整个项目中重复使用的 reducer 都是一个好主意,它们只需要返回的数据并将其转换为您需要的形状。我参与的最后一个大项目只负责客户端,它使事情更易于管理。
Apollo 客户端有类似 mapStateToProps
(Redux) 的东西吗?
假设我有一个组件,查询后我知道缓存中有数据,所以我会做类似的事情:
class Container extends React.Component {
...
...
render() {
const notes = this.props.client.readFragment(NOTES_FRAGMENT)
// notes has everything I need
return (<Child notes={notes} />);
}
}
export default WithApollo(Container);
然而,当我有一个兄弟组件调用突变并进行更新时,<Child />
组件的道具永远不会得到更新。
class AnotherContainer extends React.Component {
render() {
return(
<Mutation
mutation={UPDATE_NOTE}
update={(cache, {data: {updateNote}}) =? {
const list = cache.readFragment({
fragment: NOTES_FRAGMENT
})
// manipulate list
cache.writeFragment({fragment:NOTES_FRAGMENT, data })
}
}
)
}
}
所以我的问题是,每当我执行 writeFragment 时,如何更新 <Child />
组件的道具?有没有像 mapStateToProps 之类的东西 "connect" notes
缓存的道具,所以每当它更新时,都会触发 React 生命周期?
react-apollo
提供了三种侦听缓存变化的方法:1) Query component, 2) the graphql HOC,以及 3) 直接使用客户端调用 watchQuery
。在所有这三种情况下,您都提供了一些查询和任何适当的选项,并且您获得了一种初始获取该查询并侦听其更新的方法。
这里的关键是 queries,而不是 fragments 是读取缓存的预期载体。 readFragment
方法仅作为一次读取缓存的便捷方式(通常在突变后更改缓存的上下文中)并且不提供任何类型的反应性。
所以,最重要的是,将您的组件包装在 Query
组件或 graphql
HOC 中,您将可以访问在缓存中反映查询结果的 props,并且会在以下时间更新缓存更新(与 connect
ed 组件的方式相同)。
此时您可能会想到一些事情:
"But I don't need to make another server request!" 不用担心——默认情况下,Apollo 只会请求一次相同的查询,并将在所有后续调用中使用缓存。您可以通过为查询设置适当的 fetch policy 来修改此行为。这包括一个 cache-only
策略,它只会从缓存中提取数据(尽管默认的 cache-first
策略对于大多数用例来说已经足够了)。
"But I don't have a query to work with!" 如果您将写入缓存作为持久化某些客户端状态的一种方式,那么您应该使用 apollo-link-state这样做。
"But I don't need the entire query result, just a part of it!" graphql
HOC 提供了一个 props
函数,您可以将其传递给可以让您转换查询数据的配置成任何你想使用的形状。将渲染道具模式与 Query
组件一起使用时,并不真正需要相同的功能——您可以直接操作渲染道具。在任何一种情况下,编写一些可以在整个项目中重复使用的 reducer 都是一个好主意,它们只需要返回的数据并将其转换为您需要的形状。我参与的最后一个大项目只负责客户端,它使事情更易于管理。