路由负责将入口点定义到 Relay 应用程序中。但为了了解为什么需要路由,我们必须首先了解GraphQL查询和片段之间的区别。
附注
Relay 路由并不真正实现任何URL路由特定的逻辑或使用历史 API。在将来,我们可能会将RelayRoute重命名为更多类似于RelayQueryRoots或RelayQueryConfig的内容。有关为什么 Relay 不提供URL路由功能以及有关此类解决方案的建议的更多信息,请参阅 此帖.
在GraphQL中,查询 声明根查询类型上存在的字段。例如,下面的查询可能与获取 id
为 123
的用户名:
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') ); });