路由

路由负责将入口点定义到 Relay 应用程序中。但为了了解为什么需要路由,我们必须首先了解GraphQL查询和片段之间的区别。

附注

Relay 路由并不真正实现任何URL路由特定的逻辑或使用历史 API。在将来,我们可能会将RelayRoute重命名为更多类似于RelayQueryRoots或RelayQueryConfig的内容。有关为什么 Relay 不提供URL路由功能以及有关此类解决方案的建议的更多信息,请参阅 此帖.

查询 vs 片段 #

在GraphQL中,查询 声明根查询类型上存在的字段。例如,下面的查询可能与获取 id123 的用户名:

query UserQuery {
  user(id: "123") {
    name,
  },
}

另一方面,GraphQL 片段 声明任何类型上存在的字段。例如,以下片段为获取 一些 User配置文件图片URI。

fragment UserProfilePhoto on User {
  profilePhoto(size: $size) {
    uri,
  },
}

片段可以嵌入到其他片段或查询中。例如,上述片段可用于获取用户 123的个人资料照片:

query UserQuery {
  user(id: "123") {
    ...UserProfilePhoto,
  },
}

但是,该片段还可以获取用户 123 的每个好友的个人资料照片:

query UserQuery {
  user(id: "123") {
    friends(first: 10) {
      edges {
        node {
          ...UserProfilePhoto,
        },
      },
    },
  },
}

由于 Relay 定义了片段而不是查询,因此它们可以轻松地嵌入到多个上下文中。像 React 组件一样,Relay 容器是高度可重用的。

路由和查询 #

路由是定义一组根查询和输入参数的对象。这是一个简单的路由,可以用来呈现用户 123 的个人资料:

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
    user: () => 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',
};

如果我们想为每个用户创建一个此路由的实例,我们可以对Relay.Route 抽象类进行子类化。 Relay.Route以轻松地定义一组查询和需要重复使用的参数::

class ProfileRoute extends Relay.Route {
  static queries = {
    user: () => Relay.QL`
      query { user(id: $userID) }
    `,
  };
  static paramDefinitions = {
    // By setting `required` to true, `ProfileRoute` will throw if a `userID`
    // is not supplied when instantiated.
    userID: {required: true},
  };
  static routeName = 'ProfileRoute';
}

现在我们可以实例化一个 ProfileRoute 来获取用户 123 的数据:

// Equivalent to the object literal we created above.
var profileRoute = new ProfileRoute({userID: '123'});

但现在我们也可以为每个的用户ID创建路由。例如,如果我们想要构建一个由 userID查询参数定义的用户获取数据的路由,我们可使用:

window.addEventListener('popstate', () => {
  var userID = getQueryParamFromURI('userID', document.location.href);
  var profileRoute = new ProfileRoute({userID: userID});
  ReactDOM.render(
    <Relay.RootContainer
      Component={UserProfile}
      route={profileRoute}
    />,
    document.getElementById('app')
  );
});