readQuery在Apollo& amp; GraphQL应用程序

时间:2017-06-12 16:28:26

标签: reactjs graphql apollo react-apollo

我的应用程序有以下设置。我有一个LinkList组件,用于呈现Link个组件的列表。然后我还有一个CreateLink组件来创建新的链接。两者都使用react-router

在不同路线下呈现
<Switch>
  <Route exact path='/create' component={CreateLink}/>
  <Route exact path='/:page' component={LinkList}/>
</Switch>

我的GraphQL架构中的Link类型如下所示:

type Link implements Node {
  url: String!
  postedBy: User! @relation(name: "UsersLinks")
  votes: [Vote!]! @relation(name: "VotesOnLink")
  comments: [Comment!]! @relation(name: "CommentsOnLink")
}

我正在使用Apollo客户端,并希望在Link组件中创建新CreateLink后使用命令式商店API更新列表。

await this.props.createLinkMutation({
  variables: {
    description,
    url,
    postedById
  },
  update: (store, { data: { createLink } }) => {
    const data = store.readQuery({ query: ALL_LINKS_QUERY }) // ERROR
    console.log(`data: `, data)
  }
})

问题是store.readQuery(...)会抛出错误:

proxyConsole.js:56 Error: Can't find field allLinks({}) on object (ROOT_QUERY) {
  "allLinks({\"first\":2,\"skip\":10})": [
    {
      "type": "id",
      "id": "Link:cj3ucdguyvzdq0131pzvn37as",
      "generated": false
    }
  ],
  "_allLinksMeta": {
    "type": "id",
    "id": "$ROOT_QUERY._allLinksMeta",
    "generated": true
  }
}.

以下是我在LinkList组件中获取链接列表的方法:

export const ALL_LINKS_QUERY = gql`
  query AllLinksQuery($first: Int, $skip: Int) {
    allLinks(first: $first, skip: $skip) {
      id
      url
      description
      createdAt
      postedBy {
        id
        name
      }
      votes {
        id
      }
    }
    _allLinksMeta {
      count
    }
  }
`

export default graphql(ALL_LINKS_QUERY, {
  name: 'allLinksQuery',
  options: (ownProps) => {
    const { pathname } = ownProps.location
    const page = parseInt(pathname.substring(1, pathname.length))
    return {
      variables: {
        skip: (page - 1) * LINKS_PER_PAGE,
        first: LINKS_PER_PAGE
      },
      fetchPolicy: 'network-only'
    }
  }
}) (LinkList)

我猜这个问题与我的分页方法有某种关系,但我仍然不知道如何修复它。有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:2)

如何从商店中读取分页列表取决于您如何进行分页。如果您正在使用fetchMore,则所有数据都将存储在查询的原始密钥下,在这种情况下,我猜是使用{ first: 2, skip: 0 }获取的。这意味着为了从商店中读取更新的列表,您必须使用相同的参数,使用{ first: 2, skip: 0 }作为变量。

PS:Apollo这样做的原因是因为它仍然允许您通过变异或更新存储相对容易地更新列表。如果每个页面都是单独存储的,那么在列表的中间或开头插入一个项目会非常复杂,因为所有页面都可能需要移位。

也就是说,我们可能会引入一个名为@connection(name: "ABC")的新客户端指令,它允许您明确指定连接存储在哪个键下,而不是自动将其存储在原始变量下。如果你想在Apollo Client上打开一个问题,很高兴再谈它。<​​/ p>