在不命中服务器的情况下计算缓存数据

时间:2018-03-30 21:07:28

标签: javascript react-apollo apollo-client

假设我有以下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来获取所需数据的想法。
  • 将其包装在ApolloConsumer中以访问客户端,然后调用readQuery以获取电影列表。这保证了我不会访问数据库,但在缓存实际填充数据之前不会工作。

2 个答案:

答案 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_QUERYcache-only一起使用是一个很好而简单的解决方法。假设您没有访问公共API或者至少可以对API的设计方式施加一些控制,那么这里最干净的解决方案实际上可能是服务器端的。

而不是像这样构建你的架构:

type Query {
  movies: [Movies!]!
}

你可以改为混合一些元数据,最低限度是这样:

type Query {
  movies: QueryResult
}

type QueryResult {
  total: Int
  items: [QueryItem!]!
}

union QueryItem = Movie | Actor | Director

这样可以直接在缓存中查询总数。