假设我有以下反应组件:
import { Query } from 'react-apollo'
const MovieListContainer = () => (
<Query query={QUERY}>
{
({ loading, error, data }) => {
if (loading) return (<p>Loading...</p>)
if (error && !data) return (<p>Error...</p>)
return <MovieList movies={ data.movies }
}
}
</Query>
)
本质上,这用于从GraphQl缓存中获取电影列表(如有必要,请访问服务器(以显示。我想最大程度地减少用户看到"加载"屏幕的时间,因此初始化应用程序时可能会这样做:
import { MOVIE_QUERY } from './queries'
const client = new ApolloClient({
uri: 'http://example.com:3000/graphql'
})
// Query the movies immediately, and refresh every 30 seconds
client.query({ query: MOVIE_QUERY })
client.watchQuery({query: MOVIE_QUERY }, pollInterval: 30000)
const App = () => (
<ApolloProvider client={client}>
<Layout />
</ApolloProvider>
)
这效果很好。问题是,现在假设我想制作另一个组件来显示列表中的电影数量..
const MovieTab = ({ count }) => {
<Tab>
<span>Movies</span>
<Badge>{ count }</Badge>
</Tab>
}
如何创建一个容器以将MovieTab
挂接到Apollo缓存以获取电影列表而不会引起数据库命中(如有必要,在徽章中显示'??'(?我尝试了一些事情:
- 将其包裹在
Query
中,其中查询仅类似于movies { id }
。我已经将其作为答案,但我仍然对此并不疯狂。 - 将其包裹在
Query
中,查询是movie_query。似乎违反了使用GraphQl仅获取所需数据的想法。 - 将其包装在Apolloconsumer中以访问客户端,然后致电
readQuery
以获取电影列表。这可以保证我不会访问数据库,但是直到高速缓存实际上填充了数据。
才能使用。
这是我当前这样做的方式:
const QUERY = gql`
movies { id }
`
const MovieTabContainer = () => (
<Query query={ QUERY } fetchPolicy='cache-only'>
({ data }) => {
const count = data.movies ? data.movies.length : '??'
return (
<MovieTab count={ count } />
)
}
</Query>
)
通过指定获取策略仅缓存,我们将立即通过data
(将是一个空对象(。我们可以将其视为我们还不知道伯爵的标志。一旦通过执行完整的电影查询填充缓存,Movietab组件将被填写以包括实际的长度。
如果查询已经在其他地方获取,我认为将MOVIE_QUERY
与cache-only
一起使用是一个很好的,简单的解决方法。假设您无法访问公共API,或者至少可以对API的设计产生某种控制,那么这里最干净的解决方案实际上可能是服务器端。
而不是像这样构造您的架构:
type Query {
movies: [Movies!]!
}
您可以在一些类似的元数据中混合一些元数据:
type Query {
movies: QueryResult
}
type QueryResult {
total: Int
items: [QueryItem!]!
}
union QueryItem = Movie | Actor | Director
那会让您直接查询缓存。