中继中的容器和路由之间的查询组合如何工作?

How does query composition work between a Container and a Route in Relay?

我读过 the material 但我还是不明白。

此示例路线出现:

var profileRoute = {
  queries: {
    // Routes declare queries using functions that return a query root. Relay
    // will automatically compose the `user` fragment from the Relay container
    // paired with this route on a Relay.RootContainer
    X: () => Relay.QL`
      # In Relay, the GraphQL query name can be optionally omitted.
      query { user(id: $userID) }
    `,
  },
  params: {
    // This `userID` parameter will populate the `$userID` variable above.
    userID: '123',
  },
  // Routes must also define a string name.
  name: 'ProfileRoute',
};

(我特意将上面的 user 替换为 X,它对生成的 GraphQL 查询没有影响,以确保它对 graphql 组合没有影响)

它将与这个容器配对:

module.exports = Relay.createContainer(ProfilePicture, {
  // Specify the initial value of the `$size` variable.
  initialVariables: {
    size: 32
  },
  // For each of the props that depend on server data, we define a corresponding
  // key in `fragments`. Here, the component expects server data to populate the
  // `X` prop, so we'll specify the fragment from above as `fragments.X`.
  fragments: {
    X: () => Relay.QL`
      fragment on User {
        profilePhoto(size: $size) {
          uri,
        },
      }
    `,
  },
});

这可能会组成这样的东西:

query {
  user(id: $userID) {
    profilePhoto(size: $size) {
      uri
    }
  }
}

但是这里的逻辑是什么?也许它从片段中获取类型 User 然后寻找一种方法来获取该类型作为查询中匹配的某些内容的直接后代?也就是说,它通过编译 GraphQL 知道在 query { user(id: $userID) { X } } 中 X 标记了可以找到用户类型的位置。

到目前为止,我看到的唯一示例是在路由器中进行极其简单的线性查询。它可以更复杂吗?如果您进行的查询在两个不同的方向上进行并最终接近两个不同的 User 对象源,会发生什么情况?它怎么知道你想要哪一个?我假设不允许这样的查询。我还假设它在这些查询中唯一看到的地方是最深点,所以如果你的路由器查询类似于 query { user(id: "52") { bestFriend } },其中 bestFriend 也是一个用户,它会给你 bestFriend 而不是用户 52.

是否甚至允许在其中进行不止一层深度的查询?我试过了,我得到了这个错误:

Invariant Violation: Relay.QL: Expected query user to be empty. For example, use node(id: $id), not node(id: $id) { ... }

也许路线比我想象的要简单?也许一层深度就足够了?

构图比你想象的要简单。查询只能有一个级别的深度,并且组成组件上的同名片段(例如,在本例中 X)基本上散布 (...fragment) 到其中。

Relay理论上可以支持任意复杂的查询,但目前已有的解决方案已经足够了。这是因为可以将任意复杂的查询分解为一个简单的查询和一个新的顶级组件。

I also assume that the only place it looks in these queries is the deepest point [...]

不过,这是个好主意。