使用 Relay 和 Graphql 在根节点上进行分页

Posted

技术标签:

【中文标题】使用 Relay 和 Graphql 在根节点上进行分页【英文标题】:Pagination on root node with Relay & Graphql 【发布时间】:2018-08-05 13:58:24 【问题描述】:

努力获得这个设置并将我的头撞到墙上。我的 GraphQL DB 具有以下结构:

Graphql 架构

let Schema = () => 

  let nodeInterface, nodeField = nodeDefinitions(
    (globalId) => 

      var type, id = fromGlobalId(globalId);
      if (type === 'Grant') 
        return GrantModel.findById(id);
       else if (type === 'Scope') 
        return ScopeModel.findById(id);
       else 
        return null;
      
    ,
    (obj) => 
      if (obj instanceof ScopeModel) 
        return scopeType;
       else if (obj instanceof GrantModel)  
        return grantType;
       else 
        return null;
      
    
  );


  let grantType = new GraphQLObjectType(
    name: 'Grant',
    fields: () => (
      id: globalIdField('Grant'),
      name: type: GraphQLString,
      description: type: GraphQLString
    ),
    interface : [nodeInterface]
  );

  let scopeType = new GraphQLObjectType(
    name:'Scope',
    fields: () => (
      id: globalIdField('Scope'),
      description: type: GraphQLString,
      name: type: GraphQLString,
      enabled: type: GraphQLBoolean,
      grants: type: new GraphQLList(grantType)
    )
  );


  let connectionType: scopeConnection = connectionDefinitions(nodeType: scopeType);

  let viewerType = new GraphQLObjectType(
    name: 'Viewer',
    fields: () => (
      scopes: 
        type: scopeConnection,
        args: connectionArgs,
        resolve: async (scope, args) => connectionFromArray(await ScopeModel.find(), args)
      
    )
  );

  let schema = new GraphQLSchema(
    query: new GraphQLObjectType(
      name: 'Query',
      fields: () => (
        viewer: 
          type: viewerType,
          resolve: () => 
        
      )
    )

    /*mutation: new GraphQLObjectType(
      name: 'Mutation',
      fields: () => (
        incrementCounter: 
          type: GraphQLInt,
          resolve: () => 4
        
      )
    )*/

  );

  return schema;


export default Schema;

我有以下反应组件;注意我的index.js 是我的根组件,然后是ScopeList.js,然后是Scope.js

index.js

const IndexQueryPage = graphql`
  query IndexQuery 
    viewer 
      ...ScopeList_scopes
    
  
`;

class Index extends React.Component 
  render () 
    return (
      <div className="container">
        <table className="table">
          <thead>
            <tr>
              <th>Date Added</th>
              <th>Service</th>
              <th>Description</th>
              <th>Enabled</th>
            </tr>
          </thead>
          <QueryRenderer
           environment=environment
           query=IndexQueryPage
           variables=
           render=(error, props) => 
             console.log(props);
             if(error) 
               return <tbody><tr><td colSpan='4'></td></tr></tbody>;
             
             if(!props) 
               return <tbody><tr><td colSpan='4'>Loading.....</td></tr></tbody>;
             
             return (
               <ScopeList scopes=props.scopes />
             )
           
          />
        </table>
      </div>
    )
  


module.exports = Index;

ScopeList.js

class ScopeList extends React.Component 
  render() 
    return (
      <tbody>
       
         this.props.scopes.edges.map(edge => <Scope scope=edge.node key=edge.node.cursor />)
       
      </tbody>
    )
  


module.exports = createPaginationContainer(ScopeList, graphql`
  fragment ScopeList_scopes on Viewer
  @argumentDefinitions(
    count: type: "Int", defaultValue: 10
    cursor: type: "String"
  )
  
    scopes (
      first: $count
      after: $cursor
    ) @connection(key: "ScopeList_scopes") 
      edges 
        cursor
        node 
          id
          name
          description
        
           
    
  `,
  
    direction: 'forward',
    getConnectionFromProps(props) 
      return null;
    ,
    // This is also the default implementation of `getFragmentVariables` if it isn't provided.
    getFragmentVariables(prevVars, totalCount) 
      return 
        ...prevVars,
        count: totalCount,
      ;
    ,
    getVariables(props, count, cursor, fragmentVariables) 
      return 
        count,
        cursor
      ;
    ,
    query: graphql`
      query ScopeListQuery(
        $count: Int!
        $cursor: String
      )
        ...ScopeList_scopes @arguments(count: $count, cursor: $cursor)
      
   `
);

Scope.js

class Scope extends React.Component 
  render() 
    return (
      <tr key=this.props.scope.id>
        <td>this.props.scope.name</td>
        <td>this.props.scope.description</td>
        <td></td>
        <td></td>
      </tr>
    )
  


module.exports = createFragmentContainer(Scope, graphql `
  fragment Scope_scope on Scope 
    id
    name
    description
  
`);

基本上我正在尝试在根节点scopes 上设置分页,但是我的理解是我需要通过将其作为子节点添加到viewer 来将其作为根节点解耦。但是,我收到以下错误:

ERROR in ./app/pages/Index.js
Module not found: Error: You supplied a GraphQL document with validation errors:
component/ScopeList.js: Fragment "ScopeList_scopes" cannot be spread here as objects of type "Query" can never be of type "Viewer".
 @ ./app/pages/Index.js 28:8-53
 @ ./app/component/App.js
 @ ./app/index.js

【问题讨论】:

【参考方案1】:

无法在类型为 Query 的查询的根上传播类型为 Viewer 的片段。在查询的viewer 字段上传播该片段

【讨论】:

只是想知道为什么会这样?为什么我不能从根级别调用 anyListWithPagination?

以上是关于使用 Relay 和 Graphql 在根节点上进行分页的主要内容,如果未能解决你的问题,请参考以下文章

使用 graphql-java 构建 Relay GraphQL 服务器

GraphQL 和 Relay 中的模式之间的区别

如何从两个不同的中继连接中删除共享节点?

使用 Relay 和 GraphQL 进行查询

GraphQL 和 Relay 的概念

如何在 GraphQL (Relay) 中查询和改变数组类型?