假设我有以下React组件:
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来获取所需数据的想法。readQuery
以获取电影列表。这保证了我不会访问数据库,但在缓存实际填充数据之前不会工作。答案 0 :(得分:1)
以下是我目前的做法:
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组件以包括实际长度。
答案 1 :(得分:1)
如果查询已经被其他地方提取,我认为将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
这样可以直接在缓存中查询总数。